如何将任务添加到Task.WhenAll正在等待的集合中?

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)

Che*_*hen 6

这是因为tasks.Add(inner)之后执行的await Task.WhenAll(tasks).要回答您的问题,首先需要清除任务#3任务内部之间的关系.IMO的内部任务应该是任务#3的一部分.也就是说,任务#3在内部任务完成之前无法完成.

await inner;   //instead of tasks.Add(inner);   
Run Code Online (Sandbox Code Playgroud)


Dam*_*ver 4

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对其自身进行修改、该变量的确切正确数据类型是什么等的确切详细信息,留作练习供读者填写)