2015-07-04 9 views
8

जैसा कि मैं इसे समझता हूं, Task.Yield किसी विधि की शुरुआत में कॉलर को जारी रखने के लिए मजबूर किया जाएगा यदि यह विधि का इंतजार नहीं कर रहा है। इस बीच Task.Run और ConfigureAwait(false)both एक नए थ्रेड पूल थ्रेड पर एक कार्य चलाएं, जो कॉलर को फिर से जारी रखने के लिए मजबूर करेगा यदि यह विधि का इंतजार नहीं कर रहा है।टास्क.इल्ड, टास्क.रुन और कॉन्फ़िगरएवाइट (झूठी) के बीच क्या अंतर है?

मैं Task.Yield के बीच अंतर को समझ नहीं सकता और कॉलर पर लौटने के ठीक बाद से एक नया थ्रेड पूल थ्रेड चला रहा हूं, यह शेष विधि को निष्पादित करना जारी रखेगा, जो अनिवार्य रूप से वही बात है।

This पोस्ट पता चलता है कि Yield और Task.Factory.StartNew (जो वास्तव में सिर्फ Task.Run के पुराने संस्करण है) दूसरे के स्थान पर इस्तेमाल किया जा सकता है, जो मेरे लिए भ्रामक लगता है।

+1

कार्य.रुन = कार्य। फैक्टरी। स्टार्टन्यू – hungndv

+0

@ हंगन्दव 'कार्य। रुन'' कार्य। फैक्टरी। स्टार्टन्यू 'है लेकिन डिफ़ॉल्ट कार्य शेड्यूलर (थ्रेड पूल कार्य शेड्यूलर) पर है। 'Task.Factory।StartNew' कार्य शेड्यूलर निर्दिष्ट करने के बिना वर्तमान कार्य शेड्यूलर चुन देगा, जो डिफ़ॉल्ट नहीं हो सकता है। उदाहरण के लिए यह यूआई कार्य शेड्यूलर हो सकता है। 'कार्य। रुन' हमेशा थ्रेडपूल में निष्पादित होता है। तो, 'टास्क.रुन' 'टास्क.फैक्टरी.स्टार्टन्यू 'का एक विशेष मामला है, और ** ** ** इसका नया संस्करण –

उत्तर

6

Task.YieldTask.Run के लिए एक स्थानापन्न नहीं है और यह Task.ConfigureAwait कोई लेना देना नहीं है।

  • Task.Yield - एक प्रतीक्षा करने योग्य उत्पन्न करता है जो इसे पूरा होने के बाद चेक किया जाता है।
  • ConfigureAwait(false) - कब्जे वाले SynchronizationContext पर ध्यान देने वाले कार्य से प्रतीक्षा करने योग्य बनाता है।
  • Task.Run - ThreadPool धागे पर एक प्रतिनिधि को निष्पादित करता है। में है कि यह सब अपने आप में एक awaitable है, और नहीं एक और awaitable के विन्यास आवरण (अर्थात Task)

Task.YieldConfigureAwait से अलग है। एक और अंतर यह है कि Task.Yield कैप्चर किए गए संदर्भ पर जारी रहता है।

Task.Run दोनों अलग-अलग हैं क्योंकि यह सिर्फ एक प्रतिनिधि लेता है और इसे ThreadPool पर चलाता है, आप इसका उपयोग ConfigureAwait(false) या इसके बिना कर सकते हैं।

Task.Yield का उपयोग एसिंक्रोनस पॉइंट को मजबूर करने के लिए किया जाना चाहिए, न कि Task.Run के प्रतिस्थापन के रूप में। जब एक एसिंक विधि में प्रतीक्षा की जाती है तो यह जांचता है कि कार्य (या अन्य प्रतीक्षा योग्य) पहले ही पूरा हो चुका है और यदि ऐसा है तो यह सिंक्रनाइज़ेशन पर जारी रहता है। Task.Yield रोकता है कि ऐसा होने से यह परीक्षण के लिए उपयोगी है।

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

+3

'टास्क.इल्ड 'यूआई थ्रॉटलिंग से बचने के लिए काम नहीं करता है, क्योंकि यूआई संदेश कतारों को प्राथमिकता दी जाती है (और निरंतरता हमेशा' WM_PAINT' पर प्राथमिकता लेती है)। –

+0

इसके अलावा आप जितनी जल्दी हो सके पेंट करना कभी नहीं चाहेंगे। यह कुछ भी नहीं के लिए एक कोर जलता है। – usr

+0

@StephenCleary: यूआई संदेश कतार में निरंतरता पोस्ट कौन करता है? यह केवल तभी हो सकता है जब कुछ BeginInvoke को किसी बिंदु पर –

5

Task.Yield वर्तमान सिंक्रनाइज़ेशन संदर्भ पर या मौजूदा TaskScheduler पर मौजूद है यदि कोई मौजूद है। Task.Run ऐसा नहीं करता है। यह हमेशा थ्रेड-पूल का उपयोग करता है।

उदाहरण के लिए Task.Yield यूआई थ्रेड पर रहेगा।

Task.Yield से बचें। यह अर्थशास्त्र कम स्पष्ट हैं। लिंक किया गया जवाब एक कोड गंध है।

+0

' कार्य द्वारा 'टास्कशेड्यूलर। कंटेंट' के उपयोग के बारे में एक अच्छा बिंदु है। यील्ड '- टीपीएल टीम का एक और संदिग्ध डिजाइन निर्णय। और इसे .NET 4.0 संगतता कारणों से उचित नहीं ठहराया जा सकता है, क्योंकि .NET 4.0 में कोई 'टास्क.इल्ड' नहीं है। – Noseratio

+0

@Noseratio यह कैसे संदिग्ध है? 'प्रतीक्षा' कैप्चर किए गए संदर्भ पर जारी है जब तक कि स्पष्ट रूप से अन्यथा जो सुरक्षित रूप से नहीं बताया जाता है। यह 'टास्क.इल्ड 'के साथ अलग क्यों होना चाहिए। – i3arnon

+0

@ i3arnon, सिंक्रनाइज़ेशन संदर्भ मौजूद होने पर मैं 'टास्क.इल्ड' व्यवहार पर सवाल नहीं उठा रहा हूं। लेकिन एक की अनुपस्थिति में, मैं 'टास्कशेड्यूलर। कंटेंट 'बनाम' टास्कशेड्यूलर.डिफॉल्ट 'के उपयोग पर सवाल उठा रहा हूं। मुझे दृढ़ विश्वास है कि उत्तरार्द्ध का उपयोग किया जाना चाहिए था, क्योंकि यह 'टास्क.रुन' के साथ है। – Noseratio

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