Ble*_*ter 4 c# asynchronous async-await
是否可以将任务添加到Task.WhenAll已经等待的列表中?
我想等待所有任务完成,并且有可能在初始化后创建新任务.但是这里Task.WhenAll不会等待稍后添加到集合中的新任务.
List<Task> tasks = new List<Task>();
var task1 = Task.Run(async () =>
{
Debug.WriteLine("task #1 started");
await Task.Delay(TimeSpan.FromSeconds(20));
Debug.WriteLine("task #1 finished");
});
var task2 = Task.Run(async () =>
{
Debug.WriteLine("task #2 started");
await Task.Delay(TimeSpan.FromSeconds(30));
Debug.WriteLine("task #2 finished");
});
var task3 = Task.Run(async () =>
{
Debug.WriteLine("task #3 started");
await Task.Delay(TimeSpan.FromSeconds(10));
var inner = Task.Run(async () =>
{
Debug.WriteLine("inner task started");
await Task.Delay(TimeSpan.FromSeconds(40));
Debug.WriteLine("inner task finished");
});
tasks.Add(inner);
Debug.WriteLine("task #3 finished");
});
tasks.Add(task1);
tasks.Add(task2);
tasks.Add(task3);
await Task.WhenAll(tasks);
Debug.WriteLine("All finished");
Run Code Online (Sandbox Code Playgroud)
输出:
task #2 started
task #3 started
task #1 started
task #3 finished
inner task started
task #1 finished
task #2 finished
All finished
inner task finished < didn't wait for this to finish
Run Code Online (Sandbox Code Playgroud)
这是因为tasks.Add(inner)之后执行的await Task.WhenAll(tasks).要回答您的问题,首先需要清除任务#3和任务内部之间的关系.IMO的内部任务应该是任务#3的一部分.也就是说,任务#3在内部任务完成之前无法完成.
await inner; //instead of tasks.Add(inner);
Run Code Online (Sandbox Code Playgroud)
Task.WhenAll始终在实际开始等待之前复制对任务的引用。这确实意味着原始集合可以在等待过程中更新,但WhenAll完全忽略这些更改。
WhenAll相反,我的建议是循环运行。大致如下:
while(tasks.Count > 0) {
await Task.WhenAll(tasks);
tasks = tasks.Where(t => !t.IsCompleted);
}
Run Code Online (Sandbox Code Playgroud)
(包含您是否希望不tasks对其自身进行修改、该变量的确切正确数据类型是什么等的确切详细信息,留作练习供读者填写)