Task.WhenAll、Task.WaitAll
Task.WhenAll 和 Task.WaitAll 都是用于等待多个任务完成的方法,但它们之间有一些重要的区别。
返回类型:
Task.WhenAll: 返回一个 Task 对象,该对象表示所有输入任务的联合任务。
Task.WaitAll: 没有返回值。它是一个同步方法,会阻塞当前线程,直到所有任务完成为止。
异步/同步:
Task.WhenAll 是异步的,不会阻塞当前线程
Task.WaitAll 是同步的,会阻塞调用线程直到所有任务完成
异常处理:
Task.WhenAll 在任何一个任务出现异常时都会立即返回一个代表异常的 Task 对象,而不会等待其他任务完成。你可以通过检查返回的 Task 对象来处理异常。
Task.WaitAll 会一直等待所有任务完成,包括在其中一个任务出现异常时。异常将被捕获并包装在 AggregateException 中,需要处理这个异常。
async及await
await 关键字只能在被 async 代码块中使用。
await 关键字只能在返回类型为 Task、Task<T> 、 ValueTask<T> 的函数中使用,或在无返回值函数中使用(void)。
await 关键字是异步的,不会阻塞当前线程。此外,异步≠多线程
await 关键字会释放线程的控制权(单线程时,基于CLR的优化策略:此时,若线程有其他任务则转向其他任务,否则线程返回线程池待命;若线程待命,则待 await 结束有新任务时依旧由其执行。多线程时:若新线程完成任务后旧线程已返回线程池待命,则后续代码由新线程继续执行)
await 关键字不会主动调用新线程
await 关键字修饰的代码执行完之前,后续的代码不会执行
示例
internal class Program
{
private static async Task Main(string[] args)
{
await Console.Out.WriteLineAsync("Head-Main: " + Thread.CurrentThread.ManagedThreadId.ToString());
//TestAwait();
await TestAwait();
await Console.Out.WriteLineAsync("Foot-Main: " + Thread.CurrentThread.ManagedThreadId.ToString());
Console.Read();
}
public static async Task TestAwait()
{
await Console.Out.WriteLineAsync("Head-TestAwait: " + Thread.CurrentThread.ManagedThreadId);
string text = "";
for (int i = 0; i < 100000; i++)
{
text += "XYZ";
}
//Task.Run(() =>
//{
// File.WriteAllText(@"E://test.txt", text);
// Console.WriteLine("Write End: " + Thread.CurrentThread.ManagedThreadId);
//});
//await Task.Run(() =>
//{
// File.WriteAllText(@"E://test.txt", text);
// Console.WriteLine("Write End: " + Thread.CurrentThread.ManagedThreadId);
//});
await Console.Out.WriteLineAsync("Foot-TestAwait: " + Thread.CurrentThread.ManagedThreadId);
}
}