C# 如何将任务添加到task.WhenAll正在等待的集合中?
当所有的都在等待时,是否可以将任务添加到任务列表中 我想等待所有任务完成,并且有可能在初始化后创建新任务。但是这里的C# 如何将任务添加到task.WhenAll正在等待的集合中?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,当所有的都在等待时,是否可以将任务添加到任务列表中 我想等待所有任务完成,并且有可能在初始化后创建新任务。但是这里的Task.whalll并不等待稍后添加到集合中的新任务 List<Task> tasks = new List<Task>(); var task1 = Task.Run(async () => { Debug.WriteLine("task #1 started"); await Task.Delay(Tim
Task.whalll
并不等待稍后添加到集合中的新任务
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");
List tasks=newlist();
var task1=Task.Run(异步()=>
{
Debug.WriteLine(“任务1已启动”);
等待任务延迟(时间跨度从秒(20));
Debug.WriteLine(“任务1完成”);
});
var task2=Task.Run(异步()=>
{
Debug.WriteLine(“任务2已启动”);
等待任务延迟(时间跨度从秒(30));
Debug.WriteLine(“任务2完成”);
});
var task3=Task.Run(异步()=>
{
Debug.WriteLine(“任务3已启动”);
等待任务延迟(时间跨度从秒(10));
var internal=Task.Run(异步()=>
{
WriteLine(“内部任务已启动”);
等待任务延迟(时间跨度从秒(40));
Debug.WriteLine(“内部任务完成”);
});
任务。添加(内部);
Debug.WriteLine(“任务3完成”);
});
任务。添加(任务1);
任务。添加(任务2);
任务。添加(任务3);
等待任务。何时(任务);
Debug.WriteLine(“全部完成”);
输出:
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
任务#2已启动
任务3已开始
任务1已启动
任务#3已完成
内部任务已启动
任务#1已完成
任务#2已完成
全部完成
内部任务已完成<未等待此任务完成
这是因为任务。添加(内部)
在等待任务。所有(任务)
之后执行。要回答您的问题,首先您需要澄清task#3和task inner之间的关系。在我看来,内部任务应该是任务3的一部分。也就是说,在内部任务完成之前,任务3无法完成
await inner; //instead of tasks.Add(inner);
Task.whalll
始终在任务实际开始等待之前删除对任务的引用。这确实意味着可以在等待过程中更新原始集合,但所有的都完全忽略这些更改
相反,我建议在循环中运行。大致如下:
while(tasks.Count > 0) {
await Task.WhenAll(tasks);
tasks = tasks.Where(t => !t.IsCompleted);
}
(详细说明您是否希望将任务
本身保持不变,该变量的正确数据类型是什么,等等,留给读者作为练习填写)如果查看,您将看到在内部机制启动之前复制了集合/数组。因此,对原始集合的任何更改都不会被观察到。我认为最好的方法是手动循环-while(tasks.Count>0){wait Task.WhenAll(tasks);tasks=tasks.Where(t=>!t.IsCompleted);}
作为sketch@Damien_The_Unbeliever谢谢。我认为这是最好的解决办法。你不想写下来作为答案吗?@Blendester:我发现当人们问这个问题时,他们通常想要的是一个管道,比如TPL数据流。谢谢。但那是为了示威。新任务可以从任何位置添加到任务中。我的问题是,我希望当方法结束时,所有任务都能完成。也许我解决了一个错误的问题,但我同意这是对原始问题的解决方案,这肯定是一种代码气味。如果任务A依赖于另一个任务B的完成,那么任务A的执行应该等待任务B的完成。有关关系的更多信息,请参见下面Cheng Chen的回答。