1.無限等待
我們在使用 WhenAll 和 WaitAll 時,一定得要注意:1.必須添加超時時間,防止無限等待 2.等待的 Task 一定要保證是啟動的。
比如下面這種寫法:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace TaskForWhenAll
{
class Program
{
static void Main(string[] args)
{
var taskList = new List<Task>();
for (int i = 0; i < 5; i++)
{
taskList.Add(new Task(() =>
{
Console.WriteLine("Task {0} is finished", Task.CurrentId);
}));
}
// await Task.WhenAny(taskList);
Task.WaitAll(taskList.ToArray());
Console.WriteLine("exit");
}
}
}
將不會正常運行,會一直無限等待,因為 new Task 這樣創建出來的 Task 不會自動運行,需要手動調用 Task.Start
改造一下代碼:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace TaskForWhenAll
{
class Program
{
static void Main(string[] args)
{
var taskList = new List<Task>();
for (int i = 0; i < 5; i++)
{
taskList.Add(Task.Run(() =>
{
Console.WriteLine("Task {0} is finished", Task.CurrentId);
}));
}
// await Task.WhenAny(taskList);
Task.WaitAll(taskList.ToArray());
Console.WriteLine("exit");
}
}
}
使用 Task.Run 創建的 Task 是會自動運行的
2.沒有期望的等待
我們在創建 Task 時,可能會定義一個異步委托,以便方便在 Task 里面使用 await,例如:
class Program
{
static async Task Main(string[] args)
{
var taskList = new List<Task>();
for (int i = 0; i < 5; i++)
{
taskList.Add(Task.Factory.StartNew(async () =>
{
await Task.Delay(3000);
Console.WriteLine("Task {0} is finished", Task.CurrentId);
}));
}
await Task.WhenAny(taskList);
Console.WriteLine("exit");
}
}
直接運行會發生什么
直接就退出了,並沒有等待所有任務執行完畢。
我們換成 Task.Run 是可以正常運行的,這是為什么呢?這是因為我們這種寫法,會把 Task Result 包裝一層,我們需要得到期望的結果需要解除包裝 UnWrap,Task.Factory.StartNew和Task.Run區別之一就有Task.Run會自動執行Unwrap操作。
擴展閱讀:https://www.cnblogs.com/Leo_wl/archive/2012/09/21/2696342.html
我們改造一下代碼
taskList.Add(Task.Factory.StartNew(async () =>
{
await Task.Delay(3000);
Console.WriteLine("Task {0} is finished", Task.CurrentId);
}).Unwrap());
就能按照我們期望的去運行