2013-06-07 8 views
6

मैं पिछले 2 दिनों में सी # async विधियों के बारे में पढ़ रहा हूं और जो मैं समझता हूं, उससे (threadpool.queueuserworkitem()) धागे के विपरीत, एसिंक विधि के लिए एक कॉल तत्काल वापस नहीं आता है और यह केवल तब लौटाता है जब कॉल की गई विधि एक प्रतीक्षा या पूर्ण (या अपवाद)Async प्रोग्रामिंग नियंत्रण प्रवाह

कृपया निम्नलिखित उदाहरण देखें।

public partial class MainWindow : Window 
{ 
    // . . . 
    private async void startButton_Click(object sender, RoutedEventArgs e) 
    { 
     // ONE 
     Task<int> getLengthTask = AccessTheWebAsync(); 

     // FOUR 
     int contentLength = await getLengthTask; 

     // SIX 
     resultsTextBox.Text += 
      String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength); 
    } 


    async Task<int> AccessTheWebAsync() 
    { 
     // TWO 
     HttpClient client = new HttpClient(); 
     Task<string> getStringTask = 
      client.GetStringAsync("http://msdn.microsoft.com"); 

     // THREE     
     string urlContents = await getStringTask; 

     // FIVE 
     return urlContents.Length; 
    } 
} 

से मैं क्या इकट्ठा होते हैं, उपरोक्त कोड में, AccessTheWebAsync() तुल्यकालिक कहा जाता है (अर्थात। नियंत्रण तुरंत जब यह कहा जाता है वापस नहीं करता है)। लेकिन 'थ्री' नाम की लाइन में, रनटाइम नियंत्रण वापस कर देगा।

मेरे प्रश्न हैं:

  1. कैसे जब ThreadPool उपयोग करने के लिए या जब बुला धागे में काम चलाने के लिए क्रम तय करता है? (यानी नियंत्रण लौटने के बिना कोड निष्पादित करें)

  2. उपर्युक्त कोड में कौन से बिंदु, नए धागे (या थ्रेड पूल) का उपयोग किया जाएगा?

  3. यदि AccessTheWebAsync() ने कुछ अनुवांशिक रूप से गहन किया, तो एक अरब प्रतिरक्षण के साथ एक लूप चलाने की तरह, नियंत्रण केवल लूप पूरा होने पर कॉलर पर वापस आ जाएगा। क्या वह सही है?

  4. एसिंक फ़ंक्शन में, क्या नियंत्रण तुरंत वापस करने का एक तरीका है और फिर पृष्ठभूमि थ्रेड कहने में काम करना जारी रखें? (जैसे कि हम threadpool.queueuserworkitem())

  5. एक एसिंक विधि को कॉल करने के बिना एक एसिंक विधि को कॉल कर रहा है (यह संभव है मान लें) एक गैर async विधि को कॉल करने के समान?

उत्तर

6

पहले कुछ महत्वपूर्ण: क्रम केवल यदि का इंतजार करने के लिए कार्य अभी तक पूरा नहीं किया है await पर फोन करने वाले के लिए वापस आ जाएगी।

प्रश्न 1: मैं MSDN यहाँ उद्धृत करता हूँ:

async और इंतजार कीवर्ड अतिरिक्त धागे का कारण नहीं है बनाया जाना। Async विधियों को multithreading की आवश्यकता नहीं है क्योंकि एक async विधि अपने धागे पर नहीं चलती है।

Source

प्रश्न 2: GetStringAsync के कार्यान्वयन में हो सकता है कि लेकिन हम उस पता नहीं है और हम भी यह पता करने के लिए नहीं है। हमारे लिए यह जानना पर्याप्त है कि GetStringAsync किसी भी तरह से हमारे धागे को अवरुद्ध किए बिना इसका परिणाम प्राप्त हो जाता है।

प्रश्न 3: यदि लूप await कीवर्ड से पहले रखा गया है, हां।

प्रश्न 4: उद्धरण एक ही पैराग्राफ से पहले की तरह:

आप एक पृष्ठभूमि धागा

के लिए CPU बाध्य काम ले जाने के लिए आप async की जरूरत नहीं है Task.Run उपयोग कर सकते हैं और इसके लिए await कीवर्ड।उदाहरण:

private Task<int> DoSomethingAsync() 
{ 
    return Task.Run(() => 
    { 
     // Do CPU heavy calculation here. It will be executed in the thread pool. 
     return 1 + 1; 
    }); 
} 

प्रश्न 5: मैं उद्धृत करता हूँ फिर से

एक async प्रक्रिया आम तौर पर एक इंतजार ऑपरेटर के एक या अधिक घटनाओं में शामिल है, लेकिन इंतजार है भाव के अभाव एक संकलक त्रुटि का कारण नहीं है । यदि एक async विधि निलंबन बिंदु को चिह्नित करने के लिए एक प्रतीक्षा ऑपरेटर का उपयोग नहीं करती है, तो एसिंक संशोधक के बावजूद विधि सिंक्रोनस विधि के रूप में निष्पादित होती है। संकलक ऐसी विधियों के लिए एक चेतावनी जारी करता है।

Source (पहले की तरह ही पेज, बस एक अलग अनुभाग)

3

कैसे जब ThreadPool या जब बुला धागे में काम चलाने के लिए उपयोग करने के लिए क्रम तय करता है?

अगर वहाँ एक तुल्यकालन संदर्भ है और आप स्पष्ट रूप से आपके संदर्भ पर जारी रखने के लिए (await task.ConfigureAwait(false) की तरह कुछ का उपयोग करके) नहीं करना चाहते निर्दिष्ट नहीं करते हैं, तो विधि पर कब्जा कर लिया संदर्भ पर फिर से शुरू होगा। यूआई अनुप्रयोगों में, यह संदर्भ यूआई थ्रेड है, यह मानते हुए कि यूआई थ्रेड से विधि कहा जाता है।

उपर्युक्त कोड में कौन से बिंदु, नए धागे (या थ्रेड पूल) का उपयोग किया जाएगा?

कहीं भी नहीं। जब तक आप अन्यथा निर्दिष्ट नहीं करते हैं (ऊपर देखें), await कैप्चर किए गए संदर्भ पर वापस आ जाता है, जो आपके मामले में यूआई थ्रेड है।

तो AccessTheWebAsync() कुछ कंप्यूटेशनल रूप से संवेदनशील, एक असंख्य पुनरावृत्तियों के साथ एक पाश चल पसंद आया, नियंत्रण केवल जब पाश पूरा हो गया है फोन करने वाले के लिए वापस आ जाएगी। क्या वह सही है?

हां, मान लीजिए कि लूप पहले "असीमित" await से पहले था। (await भी "तुल्यकालिक" अगर await एड Task पहले से ही पूरा हो गया है हो सकता है।)

एक async समारोह में, वहाँ नियंत्रण तुरंत लौटने और फिर कहते हैं एक पृष्ठभूमि सूत्र में काम कर रही जारी रखने के लिए एक तरीका है?

आपको इसके लिए Task.Run() का उपयोग करना चाहिए।

एक एसिंक विधि को कॉल करने के रूप में एक एसिंक विधि को कॉल कर रहा है (यह संभव है मान लें) एक गैर async विधि को कॉल करने के समान?

यह संभव है और संकलक आपको चेतावनी देगा कि विधि पूरी तरह से सिंक्रनाइज़ेशन निष्पादित करेगी।

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