WaitAll बनाम जब सभी


335

Async CTP से Task.WaitAll()और क्या अंतर है Task.WhenAll()? क्या आप विभिन्न उपयोग के मामलों का वर्णन करने के लिए कुछ नमूना कोड प्रदान कर सकते हैं?

जवाबों:


504

Task.WaitAll सब कुछ पूरा होने तक वर्तमान धागे को अवरुद्ध करता है।

Task.WhenAllएक कार्य देता है जो सब कुछ पूरा होने तक प्रतीक्षा की कार्रवाई का प्रतिनिधित्व करता है।

इसका मतलब है कि एक async विधि से, आप उपयोग कर सकते हैं:

await Task.WhenAll(tasks);

... जिसका अर्थ है कि आपका तरीका तब तक जारी रहेगा जब सब कुछ पूरा हो जाएगा, लेकिन आप उस समय तक घूमने के लिए एक धागा नहीं बांधेंगे।


2
बहुत पढ़ने के बाद, यह स्पष्ट है कि async का थ्रेड्स ब्लॉग
विंस पानसुइयो

7
@ विंस: मुझे लगता है कि "थ्रेड्स के साथ कुछ नहीं करना है" एक ओवरस्टेटमेंट है, और यह समझना महत्वपूर्ण है कि थ्रेड के साथ async ऑपरेशंस कैसे इंटरैक्ट करते हैं।
जॉन स्कीट

6
@ केविनबुई: नहीं, इसे अवरुद्ध नहीं करना चाहिए - यह कार्य के द्वारा लौटाए जाने का इंतजार करेगा WhenAll, लेकिन यह धागे को अवरुद्ध करने के समान नहीं है।
जॉन स्कीट

1
@JonSkeet शायद उन दोनों के बीच सटीक अंतर मेरे लिए बहुत सूक्ष्म है। क्या आप कुछ संदर्भ में मुझे (और संभवतः, बाकी लोगों को) इंगित कर सकते हैं जो अंतर स्पष्ट करेंगे?
कैटशॉ

125
@CatShoes: वास्तव में नहीं - मैंने इसे पहले ही समझा दिया है। मुझे लगता है कि मैं एक सादृश्य दे सकता हूं - यह एक टेकअवे के आदेश के बीच अंतर की तरह है और फिर दरवाजे के पास आने के लिए इंतजार कर रहा है, बनाम एक टेकवे का आदेश दे रहा है, अन्य सामान कर रहा है और फिर कूरियर के आने पर दरवाजा खोल रहा है ...
जॉन स्कीट

51

जबकि जॉनस्केट का जवाब आम तौर पर उत्कृष्ट तरीके से अंतर को बताता है: एक और अंतर है: अपवाद हैंडलिंग

Task.WaitAllएक फेंकता है AggregateExceptionजब कार्यों के किसी भी फेंकता है और आप सभी फेंका अपवाद की जांच कर सकते हैं। awaitमें await Task.WhenAllunwraps AggregateExceptionऔर 'रिटर्न' केवल प्रथम अपवाद।

जब नीचे दिए गए प्रोग्राम await Task.WhenAll(taskArray)आउटपुट के साथ निष्पादित होता है।

19/11/2016 12:18:37 AM: Task 1 started
19/11/2016 12:18:37 AM: Task 3 started
19/11/2016 12:18:37 AM: Task 2 started
Caught Exception in Main at 19/11/2016 12:18:40 AM: Task 1 throwing at 19/11/2016 12:18:38 AM
Done.

जब Task.WaitAll(taskArray)आउटपुट के साथ नीचे दिए गए प्रोग्राम को निष्पादित किया जाता है।

19/11/2016 12:19:29 AM: Task 1 started
19/11/2016 12:19:29 AM: Task 2 started
19/11/2016 12:19:29 AM: Task 3 started
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 1 throwing at 19/11/2016 12:19:30 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 2 throwing at 19/11/2016 12:19:31 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 3 throwing at 19/11/2016 12:19:32 AM
Done.

कार्यक्रम:

class MyAmazingProgram
{
    public class CustomException : Exception
    {
        public CustomException(String message) : base(message)
        { }
    }

    static void WaitAndThrow(int id, int waitInMs)
    {
        Console.WriteLine($"{DateTime.UtcNow}: Task {id} started");

        Thread.Sleep(waitInMs);
        throw new CustomException($"Task {id} throwing at {DateTime.UtcNow}");
    }

    static void Main(string[] args)
    {
        Task.Run(async () =>
        {
            await MyAmazingMethodAsync();
        }).Wait();

    }

    static async Task MyAmazingMethodAsync()
    {
        try
        {
            Task[] taskArray = { Task.Factory.StartNew(() => WaitAndThrow(1, 1000)),
                                 Task.Factory.StartNew(() => WaitAndThrow(2, 2000)),
                                 Task.Factory.StartNew(() => WaitAndThrow(3, 3000)) };

            Task.WaitAll(taskArray);
            //await Task.WhenAll(taskArray);
            Console.WriteLine("This isn't going to happen");
        }
        catch (AggregateException ex)
        {
            foreach (var inner in ex.InnerExceptions)
            {
                Console.WriteLine($"Caught AggregateException in Main at {DateTime.UtcNow}: " + inner.Message);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Caught Exception in Main at {DateTime.UtcNow}: " + ex.Message);
        }
        Console.WriteLine("Done.");
        Console.ReadLine();
    }
}

13
सबसे बड़ा व्यावहारिक अंतर अपवाद हैंडलिंग है। वास्तव में? क्योंकि वह वास्तव में सबसे बड़ा व्यावहारिक अंतर नहीं है। सबसे बड़ा व्यावहारिक अंतर यह है कि async और नॉन-ब्लॉकिंग जहाँ अन्य अवरुद्ध है। यह बहुत अधिक महत्वपूर्ण है कि यह अपवादों को कैसे संभालता है।
लियाम

5
इस पर ध्यान दिलाने के लिए धन्यवाद। यह स्पष्टीकरण उस परिदृश्य में उपयोगी था जो मैं वर्तमान में काम कर रहा हूं। शायद "सबसे बड़ा व्यावहारिक अंतर" नहीं है, लेकिन निश्चित रूप से एक अच्छा कॉल आउट है।
उर्क

अपवाद है सबसे बड़ी व्यावहारिक अंतर से निपटने के बीच तुलना करने के लिए और अधिक लागू हो सकता है await t1; await t2; await t3;बनामawait Task.WhenAll(t1,t2,t3);
frostshoxx

1
क्या यह अपवाद व्यवहार यहां डॉक्स का विरोधाभासी नहीं करता है ( docs.microsoft.com/en-us/dotnet/api/… ) "यदि आपूर्ति किए गए कार्यों में से कोई भी एक दोषपूर्ण स्थिति में पूरा होता है, तो लौटाया गया कार्य भी एक दोषपूर्ण स्थिति में पूरा होगा , जहां इसके अपवादों में आपूर्ति किए गए कार्यों में से प्रत्येक को अलिखित अपवादों के समूह का एकत्रीकरण होगा। "
दासिथ विज

1
मैं इसे एक कलाकारी मानता हूं await, न कि दो तरीकों के बीच का अंतर। दोनों एक प्रचार करते हैं AggregateException, या तो सीधे या एक संपत्ति ( Task.Exceptionसंपत्ति) के माध्यम से फेंकते हैं।
थियोडोर जूलियास

20

अंतर के एक उदाहरण के रूप में - यदि आपके पास कोई कार्य UI थ्रेड के साथ कुछ करता है (उदाहरण के लिए एक कार्य जो कि स्टोरीबोर्ड में एक एनीमेशन का प्रतिनिधित्व करता है) तो यदि आप Task.WaitAll()यूआई धागा अवरुद्ध है और यूआई कभी अपडेट नहीं किया जाता है। यदि आप उपयोग करते हैं await Task.WhenAll()तो UI थ्रेड ब्लॉक नहीं किया जाता है, और UI अपडेट किया जाएगा।


7

वो क्या करते हैं:

  • आंतरिक रूप से दोनों एक ही काम करते हैं।

क्या फर्क पड़ता है:

  • WaitAll एक ब्लॉकिंग कॉल है
  • जब सभी - कोड का निष्पादन जारी रहेगा

जब उपयोग करें:

  • WaitAll जब परिणाम के बिना जारी नहीं रख सकते
  • WhenAll जब क्या सिर्फ अधिसूचित किया जाना, अवरुद्ध नहीं

1
@MartinRhodes लेकिन क्या होगा अगर आप तुरंत इसका इंतजार नहीं करते हैं, लेकिन किसी और काम के साथ जारी रखते हैं और फिर इसका इंतजार करते हैं? WaitAllजैसा कि मैं इसे समझता हूं, आपके पास वह संभावना नहीं है ।
जेप्पे

@Jeppe क्या आपने अपने कुछ अन्य काम करने के Task.WaitAll बाद सिर्फ कॉल को अलग नहीं किया? मेरा मतलब है, अपने कार्यों को शुरू करने के बाद इसे सही कहने के बजाय।
पीएल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.