2016-10-25 19 views
5

क्या मैं MSDNasync का इंतजार है और

पर async पढ़ सकते हैं और इंतजार कीवर्ड अतिरिक्त धागे बनाया जा करने के लिए कारण नहीं है के आधार पर सूत्रण। क्योंकि एक async विधि अपनी ही धागे पर नहीं चलता है Async तरीकों बहु सूत्रण आवश्यकता नहीं है। विधि वर्तमान तुल्यकालन संदर्भ पर चलता है और धागा केवल जब विधि सक्रिय है या समय का उपयोग करता है। आप Task.Run एक पृष्ठभूमि धागा करने के लिए सीपीयू बाध्य काम ले जाने के लिए उपयोग कर सकते हैं, लेकिन एक पृष्ठभूमि धागा एक प्रक्रिया कि सिर्फ परिणाम उपलब्ध होने के लिए इंतजार कर रहा है के साथ मदद नहीं करता है।

यह मूल रूप से कह रहा है कि कोई धागा नहीं बनाया जाएगा। लेकिन एक वर्ग है जो मुझे विरासत में मिला HttpClient मैं कुछ दिलचस्प पाया ..

async Task<T> SendAsync<T>(HttpMethod method, Uri uri, HttpContent content, CancellationToken cancellationToken) 
{ 
     HttpRequestMessage msg = new HttpRequestMessage(method, uri); 
     msg.Content = content; 
     //On Main Thread 
     HttpResponseMessage response = await SendAsync(msg, cancellationToken); 
     //On worker thread 
     //... 
} 

विधि static void Main

Task result = client.GetAsync<string>(...); 
//GetAsync calls await SendAsync<T> 
result.Wait(); 

मैं क्यों await SendAsnc कॉल के बाद एक अलग थ्रेड पर कर रहा हूँ अंदर कहा जाता है के अंदर ?? मैंने सोचा कि एसिन कोई नया धागा नहीं बनाता है। या कम से कम इसे प्रतीक्षा के बाद मूल धागे पर वापस बुलाया जाएगा।

+0

यदि आपके पास * सिंक्रनाइज़ेशन संदर्भ नहीं है, तो एक async विधि से निरंतरता थ्रेडपूल थ्रेड पर चलती है। कंसोल अनुप्रयोग (जिसे मैं मान रहा हूं, जैसा कि आप 'मुख्य() 'संदर्भित करते हैं) डिफ़ॉल्ट रूप से सिंक्रनाइज़ेशन संदर्भ नहीं है। –

उत्तर

9

यह दस्तावेज़ीकरण में खराब विज्ञापन है, लेकिन कंसोल एप्लिकेशन में सिंक्रनाइज़ेशन संदर्भ की कमी के कारण यूआई अनुप्रयोग में यह कैसे काम करता है, इस तरह से कंसोल एप्लिकेशन में async/await काम करता है। This article विवरण का वर्णन करता है और कैसे एक तो यह है कि async/इंतजार बर्ताव में एक अधिक पूर्वानुमान रास्ता जोड़ने का एक कोड नमूना देता है।

आम तौर पर, आप async के बारे में बिल्कुल सही कर रहे हैं/नहीं का इंतजार जरूरी entailing बहु सूत्रण (हालांकि Task.Run तरह बातें प्रश्न में करते हैं, वास्तव में, कारण कोड थ्रेड पूल में चलाने के लिए), लेकिन (जैसा कि मैंने लिंक किए गए लेख में वर्णित है) एक कंसोल अनुप्रयोग async/प्रतीक्षा में कहीं भी चला सकता है।

उसी सामान्य थ्रेड पर चलने पर एसिंक काम करता है, इसके बारे में मेरा सामान्य सादृश्य 9 अन्य लोगों (इसलिए कुल 10 लोगों) के साथ एक रेस्तरां में जाने के बारे में सोचना है। जब वेटर आता है, तो 9 लोग तैयार हैं और 10 वीं नहीं है। इस मामले में, वेटर दूसरे 9 लोगों के आदेश पहले ले जाएगा और फिर 10 वें व्यक्ति के पास वापस आ जाएगा। यदि किसी भी कारण से 10 वें व्यक्ति वास्तव में धीमा हो गया है तो वेटर हमेशा ऑर्डर वापस रसोई में ला सकता है और 10 वें व्यक्ति के तैयार होने पर वापस आ सकता है।

स्पष्ट रूप से, 10 वें व्यक्ति को ऑर्डर करने के लिए तैयार होने के लिए बस एक दूसरा वेटर लाने का कोई मतलब नहीं है, और यह स्पष्ट रूप से अक्षम होगा कि हर किसी को एक व्यक्ति को तैयार होने की प्रतीक्षा करें। स्थिति में अतिरिक्त वेटर्स जोड़ने से चीजें तेज नहीं होंगी क्योंकि देरी की कमी के कारण देरी नहीं हो रही है, क्योंकि 10 वें व्यक्ति के दिमाग को धीमा करने के कारण धीमा हो रहा है (और प्रतीक्षा कर्मचारी इसके बारे में कुछ भी नहीं कर सकते)।

6

मैं अपने introduction to async blog post में इस व्यवहार का वर्णन।

सारांश में, यह सही है:

async और इंतजार कीवर्ड का कारण नहीं है अतिरिक्त धागे बनाया जाना।

मैंने सोचा था कि asyn कोई नया थ्रेड creats:

और इसलिए यह है।

यह सही नहीं है:

या कम से कम यह इंतजार के बाद वास्तविक थ्रेड को वापस सक्रिय किया जाएगा।

async और await - खुद को द्वारा - किसी भी अतिरिक्त धागे बनाया जाना कारण नहीं है। हालांकि, await पूर्ण होने के बाद, async विधि का शेष कहीं चलाया जाना चाहिए।

डिफ़ॉल्ट रूप से, await वर्तमान SynchronizationContext (जब तक यह null, जिस स्थिति में वर्तमान संदर्भ वर्तमान TaskScheduler है) एक "संदर्भ" है, जो कैप्चर करता है। यूआई थ्रेड्स का अपना सिंक्रनाइज़ेशन संदर्भ होता है (उदा।, WinFormsSynchronizationContext या DispatcherSynchronizationContext), और उस स्थिति में, async विधि उसी UI थ्रेड पर निष्पादन जारी रहेगी।

कंसोल अनुप्रयोग में, कोई सिंक्रनाइज़ेशन संदर्भ नहीं है, इसलिए await द्वारा कैप्चर किया गया "संदर्भ" थ्रेड पूल संदर्भ होगा। इस प्रकार, जब async विधि फिर से शुरू करने के लिए तैयार है, तो इसे थ्रेड पूल पर निर्धारित किया जाएगा और वहां कुछ धागे से उठाया जाएगा।

1

कंसोल अनुप्रयोगों में एक थंक पूल सिंक्रनाइज़ेशन कॉन्टेक्स्ट होता है जो एक-चंक-एट-ए-टाइम सिंक्रनाइज़ेशन कॉन्टेक्स्ट के बजाय जीयूआई और एएसपी.NET अनुप्रयोगों में उपयोग किया जाता है, इसलिए जब प्रतीक्षा पूरी होती है, तो यह एसिंक विधि के शेष को शेड्यूल करता है एक धागा पूल धागा। एसिंक प्रतीक्षा व्यवहार के बारे में अधिक जानकारी के लिए this article पढ़ें।

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