2009-10-24 19 views
7

मैं अपनी कुछ परियोजनाओं में एसिंक्रोनस विधियों का उपयोग कर रहा हूं और मुझे यह पसंद है क्योंकि यह मेरे एप्लिकेशन को बहुत अधिक स्केलेबल होने की अनुमति देता है। हालांकि, मैं सोच रहा हूं कि एसिंक्रोनस विधियां वास्तव में पृष्ठभूमि में कैसे काम करती हैं? कैसे .NET (या Windows?) जानता है कि एक कॉल पूरा हो गया है? मेरे द्वारा बनाई गई एसिंक्रोनस कॉल की संख्या के आधार पर, मैं देख सकता हूं कि नए धागे बनाए गए हैं (हमेशा नहीं ...)। क्यूं कर?सी # में एसिंक्रोनस विधियां कैसे काम करती हैं?

इसके अतिरिक्त, मैं निगरानी करना चाहता हूं कि अनुरोध कब तक पूरा हो जाएगा। अवधारणा का परीक्षण करने के लिए, मैंने निम्न कोड लिखा है जो एक वेब सेवा को असीमित रूप से कॉल करता है और स्टॉपवॉच शुरू करने के तुरंत बाद।

for (int i = 0; i < 10000; i++) 
{ 
    myWebService.BeginMyMethod(new MyRequest(), result, new AsyncCallback(callback), i); 
    stopWatches[i].Start(); 
} 
// Call back stop the stopwatch after calling EndMyMethod 

यह काम नहीं करता क्योंकि सभी अनुरोधों (10000) एक ही है समय शुरू और अवधि रैखिक बढ़ जाएगी (0 फोन = अवधि 1, फोन 1 = अवधि 2, आदि)। मैं एसिंक्रोनस विधि के साथ कॉल की वास्तविक अवधि की निगरानी कैसे कर सकता हूं (उस क्षण से अनुरोध वास्तव में अंत तक निष्पादित किया जाता है)?


अद्यतन: एक अतुल्यकालिक विधि प्रवाह को ब्लॉक करता है? मैं समझता हूं कि यह .NET ThreadPool का उपयोग करता है लेकिन कैसे IAsyncResult जानता है कि एक कॉल पूरा हो गया है और अब CallBack विधि को कॉल करने का समय है?

+0

1. थ्रेडपूल, 2. थ्रेडपूल कैसे काम करता है इस बारे में विस्तार देखें लेकिन मुझे नहीं लगता कि आप जो चाहते हैं वह सामान्य तरीके से संभव है। http://msdn.microsoft.com/en-us/library/ms973903.aspx –

उत्तर

3

कोड रेल मार्ग है और धागा ट्रेन है। जैसे ही रेलवे रेलगाड़ी जाती है, यह कोड निष्पादित करती है।

BeginMyMethod मुख्य धागे द्वारा निष्पादित किया जाता है। यदि आप BeginMyMethod के अंदर देखते हैं तो यह MyMethod का प्रतिनिधि ThreadPool की कतार में जोड़ता है।वास्तविक MyMethod ट्रेन पूल की गाड़ियों में से एक ने मार डाला जाता है। पूरा होने वाला दिनचर्या जिसे MyMethod कहा जाता है, उसी थ्रेड द्वारा निष्पादित किया जाता है जो MyMethod निष्पादित करता है, न कि आपके मुख्य थ्रेड द्वारा जो शेष कोड चलाता है। जबकि एक थ्रेड पूल धागा क्रियान्वित MyMethod व्यस्त है, मुख्य थ्रेड रेल प्रणाली के कुछ अन्य भाग (कुछ अन्य कोड निष्पादित) की सवारी कर सकते हैं, या बस सो, जब तक कुछ सेमाफोर जलाया जाता है इंतज़ार कर रहे।

इसलिए IAsyncResult जैसी कोई चीज नहीं "जानने" जब पूरा होने दिनचर्या कॉल करने के लिए, बजाय, पूरा होने के नियमित बस एक प्रतिनिधि थ्रेड पूल के धागे से बुलाया सही होने के बाद यह MyMethod को क्रियान्वित किया है है।

मुझे उम्मीद है कि आप कुछ हद तक बचपन की ट्रेन समानता को ध्यान में रखते हैं, मुझे पता है कि लोगों को बहुसंख्यक व्याख्या करते समय मुझे एक से अधिक बार मेरी मदद मिली।

+0

मैं ट्रेन सादृश्य पसंद है! धन्यवाद! :) – Martin

1

इसका क्रूक्स यह है कि Begin को आपकी विधि को निष्पादित करने के अनुरोध पर कतारबद्ध है। विधि वास्तव में थ्रेडपूल पर निष्पादित की जाती है, जो रनटाइम द्वारा प्रदान किए गए कार्यकर्ता धागे का एक सेट है।

थ्रेडपूल एसिंक कार्यों के माध्यम से क्रंच करने के लिए धागे का एक निश्चित सेट है क्योंकि उन्हें कतार में डाल दिया जाता है। यह बताता है कि आप निष्पादन समय को लंबे और लंबे समय तक क्यों देखते हैं - आपकी विधियां लगभग एक ही समय में निष्पादित हो सकती हैं, लेकिन जब तक कि कतार में सभी पिछली विधियों को निष्पादित नहीं किया जाता है तब तक वे प्रारंभ नहीं होते हैं।

वास्तव में एसिंक विधि को निष्पादित करने में लगने वाले समय की निगरानी करने के लिए, आपको अपनी विधि की शुरुआत और अंत में टाइमर शुरू करना और रोकना होगा।

ThreadPool कक्षा के लिए दस्तावेज़ और async methods के बारे में एक लेख है जो यह बताते हुए बेहतर काम करता है कि क्या हो रहा है।

1

असीमित तरीके .NET ThreadPool का उपयोग कर काम करते हैं। पृष्ठभूमि में काम करने के लिए वे काम को ThreadPool धागे (संभावित रूप से आवश्यक होने पर एक बनाते हैं, लेकिन आम तौर पर केवल एक का उपयोग कर) पर धक्का देंगे।

अपने मामले में, आप जो कर रहे हैं वह कर सकते हैं, हालांकि, एहसास है कि ThreadPool में सीमित संख्या में धागे हैं जिनके साथ यह काम करेगा। आप अपने काम को पृष्ठभूमि धागे पर फैलाने जा रहे हैं, और पहला तुरंत चलाएगा, लेकिन थोड़ी देर के बाद, वे कतारबद्ध होंगे, और "कार्य" पूरी तरह से पहले तक काम नहीं करेंगे। यह लंबे और लंबे समय तक चलने वाले धागे की उपस्थिति देगा।

हालांकि, आपके स्टॉपवॉच मानदंड कुछ हद तक त्रुटिपूर्ण हैं। आपको एन कार्यों को पूरा करने के लिए कुल समय को मापना चाहिए, न कि एक कार्य को पूरा करने के लिए एन बार। यह एक और अधिक उपयोगी मीट्रिक होगा।

0

यह संभव है कि अधिकांश निष्पादन समय BeginMyMethod() से पहले होता है। उस मामले में अपने माप बहुत कम हो जाएगा। वास्तव में, एपीआई के आधार पर, BeginMyMethod() कॉलबैक ढेर ही रवाना होने से पहले कह सकते हैं। StopWatch.Start() करने के लिए कॉल ऊपर जा रहा है तो मदद करनी चाहिए।

संबंधित मुद्दे