मैंने सिर्फ Task.WhenAll
.NET कोर 3.0 पर चलने के दौरान विधि के बारे में एक उत्सुक अवलोकन किया । मैंने एक साधारण Task.Delay
कार्य को एक तर्क के रूप में पारित किया Task.WhenAll
, और मुझे उम्मीद थी कि लिपटे हुए कार्य मूल कार्य के लिए समान रूप से व्यवहार करेंगे। पर ये स्थिति नहीं है। मूल कार्य की निरंतरता को एसिंक्रोनस रूप से निष्पादित किया जाता है (जो वांछनीय है), और एकाधिक Task.WhenAll(task)
आवरणों की निरंतरता को एक के बाद एक (जो अवांछनीय है) को एक साथ निष्पादित किया जाता है।
यहाँ इस व्यवहार का एक डेमो है। चार कार्यकर्ता कार्यों Task.Delay
को पूरा करने के लिए समान कार्य की प्रतीक्षा कर रहे हैं , और फिर एक भारी गणना (एक द्वारा सिम्युलेटेड Thread.Sleep
) के साथ जारी रखें ।
var task = Task.Delay(500);
var workers = Enumerable.Range(1, 4).Select(async x =>
{
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}" +
$" [{Thread.CurrentThread.ManagedThreadId}] Worker{x} before await");
await task;
//await Task.WhenAll(task);
Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}" +
$" [{Thread.CurrentThread.ManagedThreadId}] Worker{x} after await");
Thread.Sleep(1000); // Simulate some heavy CPU-bound computation
}).ToArray();
Task.WaitAll(workers);
यहाँ आउटपुट है। अलग-अलग थ्रेड्स (समानांतर में) के अनुसार चार निरंतरता चल रही है।
05:23:25.511 [1] Worker1 before await
05:23:25.542 [1] Worker2 before await
05:23:25.543 [1] Worker3 before await
05:23:25.543 [1] Worker4 before await
05:23:25.610 [4] Worker1 after await
05:23:25.610 [7] Worker2 after await
05:23:25.610 [6] Worker3 after await
05:23:25.610 [5] Worker4 after await
अब अगर मैं लाइन पर टिप्पणी करता हूं await task
और निम्नलिखित लाइन को अनसुना करता हूं await Task.WhenAll(task)
, तो आउटपुट काफी अलग है। सभी निरंतरता एक ही धागे में चल रही है, इसलिए गणनाओं को समानांतर नहीं किया गया है। प्रत्येक गणना पिछले एक के पूरा होने के बाद शुरू हो रही है:
05:23:46.550 [1] Worker1 before await
05:23:46.575 [1] Worker2 before await
05:23:46.576 [1] Worker3 before await
05:23:46.576 [1] Worker4 before await
05:23:46.645 [4] Worker1 after await
05:23:47.648 [4] Worker2 after await
05:23:48.650 [4] Worker3 after await
05:23:49.651 [4] Worker4 after await
आश्चर्यजनक रूप से यह तभी होता है जब प्रत्येक कार्यकर्ता एक अलग रैपर का इंतजार करता है। अगर मैं रैपर को परिभाषित करता हूं:
var task = Task.WhenAll(Task.Delay(500));
... और फिर await
सभी श्रमिकों के अंदर एक ही कार्य, व्यवहार पहले मामले (अतुल्यकालिक निरंतरता) के समान है।
मेरा सवाल है: ऐसा क्यों हो रहा है? एक ही कार्य के अलग-अलग रैपरों को एक ही धागे में, समान रूप से निष्पादित करने के लिए क्या कारण हैं?
नोट: एक ही अजीब व्यवहार में परिणामों के Task.WhenAny
बजाय किसी कार्य को लपेटना Task.WhenAll
।
एक और अवलोकन: मुझे उम्मीद थी कि आवरण को लपेटने Task.Run
से निरंतरता अतुल्यकालिक होगी। लेकिन ऐसा नहीं हो रहा है। नीचे की पंक्ति की निरंतरता को अभी भी एक ही धागे में (समकालिक रूप से) निष्पादित किया जाता है।
await Task.Run(async () => await Task.WhenAll(task));
स्पष्टता: .NET कोर 3.0 प्लेटफॉर्म पर चल रहे कंसोल एप्लिकेशन में उपरोक्त अंतर देखे गए। .NET फ्रेमवर्क 4.8 पर, मूल कार्य या कार्य-आवरण की प्रतीक्षा करने में कोई अंतर नहीं है। दोनों मामलों में, एक ही धागे में निरंतरता को समान रूप से निष्पादित किया जाता है।
Task.WhenAll
Task.Delay
से 100
करने के लिए 1000
इसे पूरा नहीं किया जाता है, ताकि जब await
एड।
await Task.WhenAll(new[] { task });
?