Sự khác biệt giữa Task.WaitAll()
và Task.WhenAll()
từ Async CTP là gì? Bạn có thể cung cấp một số mã mẫu để minh họa các trường hợp sử dụng khác nhau?
Sự khác biệt giữa Task.WaitAll()
và Task.WhenAll()
từ Async CTP là gì? Bạn có thể cung cấp một số mã mẫu để minh họa các trường hợp sử dụng khác nhau?
Câu trả lời:
Task.WaitAll
chặn luồng hiện tại cho đến khi mọi thứ đã hoàn thành.
Task.WhenAll
trả về một nhiệm vụ đại diện cho hành động chờ đợi cho đến khi mọi thứ đã hoàn thành.
Điều đó có nghĩa là từ phương thức async, bạn có thể sử dụng:
await Task.WhenAll(tasks);
... Điều đó có nghĩa là phương pháp của bạn sẽ tiếp tục khi mọi thứ hoàn thành, nhưng bạn sẽ không buộc một sợi chỉ để treo xung quanh cho đến lúc đó.
WhenAll
, nhưng điều đó không giống như chặn chuỗi.
Trong khi câu trả lời của JonSkeet giải thích sự khác biệt theo cách điển hình xuất sắc, có một sự khác biệt khác: xử lý ngoại lệ .
Task.WaitAll
ném một AggregateException
khi bất kỳ nhiệm vụ nào ném và bạn có thể kiểm tra tất cả các ngoại lệ ném. Các await
trong await Task.WhenAll
unwraps AggregateException
và 'lợi nhuận' chỉ là ngoại lệ đầu tiên.
Khi chương trình dưới đây thực hiện với await Task.WhenAll(taskArray)
đầu ra như sau.
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.
Khi chương trình dưới đây được thực hiện với Task.WaitAll(taskArray)
đầu ra như sau.
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.
Chương trình:
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();
}
}
await t1; await t2; await t3;
vsawait Task.WhenAll(t1,t2,t3);
await
, không phải là một sự khác biệt giữa hai phương pháp. Cả hai tuyên truyền một AggregateException
, hoặc ném trực tiếp hoặc thông qua một tài sản ( Task.Exception
tài sản).
Như một ví dụ về sự khác biệt - nếu bạn có một nhiệm vụ, thì hãy thực hiện điều gì đó với luồng UI (ví dụ: một tác vụ đại diện cho hoạt hình trong Storyboard) nếu bạn Task.WaitAll()
thì luồng UI bị chặn và UI không bao giờ được cập nhật. nếu bạn sử dụng await Task.WhenAll()
thì luồng UI không bị chặn và UI sẽ được cập nhật.
Họ làm gì:
Có gì khác biệt:
Sử dụng khi nào:
WaitAll
như tôi hiểu.
Task.WaitAll
sau khi bạn đã thực hiện một số công việc khác của bạn? Ý tôi là, thay vì gọi nó ngay sau khi bắt đầu nhiệm vụ của bạn.