2015-02-10 8 views
12

यह कोड स्निपेट Stephen Cleary's blog से है और कार्य का उपयोग करते समय प्रगति की रिपोर्ट करने का एक उदाहरण देता है। Run। मैं जानना चाहता हूं कि यूआई को अपडेट करने के साथ कोई क्रॉस थ्रेड समस्या क्यों नहीं है, जिसके द्वारा मेरा मतलब है कि क्यों आह्वान की आवश्यकता नहीं है?कार्य.रुन और यूआई प्रगति अद्यतन

private async void button2_Click(object sender, EventArgs e) 
{ 
    var progressHandler = new Progress<string>(value => 
    { 
     label2.Text = value; 
    }); 
    var progress = progressHandler as IProgress<string>; 
    await Task.Run(() => 
    { 
     for (int i = 0; i != 100; ++i) 
     { 
      if (progress != null) 
       progress.Report("Stage " + i); 
      Thread.Sleep(100); 
     } 
    }); 
    label2.Text = "Completed."; 
} 
+0

@newbieguy स्ट्रिंग concatenations स्वचालित रूप से ToString() विधि को कॉल करता है –

उत्तर

19

Progress<T> पकड़ता वर्तमान SynchronisationContext जब यह instantiated है। जब भी आप Report पर कॉल करते हैं, तो यह गुप्त रूप से कब्जे वाले संदर्भ में प्रतिनिधि करता है। उदाहरण में, कब्जा कर लिया संदर्भ यूआई है, जिसका अर्थ है कि कोई अपवाद नहीं होता है।

+0

क्या आपको पता है कि इस पर थ्रेड प्राथमिकता क्या दी गई है?यानी: सामान्य, पृष्ठभूमि, अनुप्रयोग इत्यादि .. – Kelly

+0

@ केली प्रेषक प्राथमिकता सामान्य है। यहां टिप्पणी अनुभाग देखें https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchersynchronizationcontext.post(v=vs.110).aspx – Gusdor

8

Progress<T> कन्स्ट्रक्टर वर्तमान SynchronizationContext ऑब्जेक्ट को कैप्चर करता है।

SynchronizationContext कक्षा एक ऐसी सुविधा है जो शामिल थ्रेडिंग मॉडल के विवरण को सारणीबद्ध करती है। यही कारण है, विंडोज, फॉर्म्स यह Control.Invoke का उपयोग करेगा, WPF में यह Dispatcher.Invoke का उपयोग करेगा आदि

जब progress.Report वस्तु कहा जाता है, Progress वस्तु ही जानता है कि यह कब्जा कर लिया SynchronizationContext का उपयोग कर अपने प्रतिनिधि चलाना चाहिए में।

अन्य शर्तों में, यह काम करता है क्योंकि Progress को डेवलपर को स्पष्ट रूप से कहने के बिना इसे संभालने के लिए डिज़ाइन किया गया है।

4

ऐसा लगता है आप तथ्य यह है कि इस पार से धागा मशीनरी का हिस्सा डेवलपर आंखों से छिपा हुआ है ताकि आप सिर्फ "लेने के लिए और का उपयोग करें" के लिए है है की वजह से उलझन में कर रहे हैं: http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis.aspx

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

हमने प्रगति कक्षा भी प्रदान की, जो आईप्रेशंस का कार्यान्वयन है। आपको कार्यान्वयन में प्रगति का उपयोग करने के लिए प्रोत्साहित किया जाता है, क्योंकि यह को सहेजने और सिंक्रनाइज़ेशन संदर्भ को पुनर्स्थापित करने के आसपास सभी बहीखाता को संभालता है। प्रगति ईवेंट और एक एक्शन कॉलबैक दोनों को उजागर करती है, जिसे कार्य रिपोर्ट प्रगति के समय कहा जाता है। यह पैटर्न आपको कोड लिखने में सक्षम बनाता है जो प्रगति परिवर्तनों के संदर्भ में प्रतिक्रिया करता है। साथ में, आईप्र्रेस और प्रगति यूआई थ्रेड पर पृष्ठभूमि कार्य से प्रगति जानकारी पास करने का एक आसान तरीका प्रदान करती है।

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

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