使用tpl已经有一段时间了,我还有一些谜团要解决:)
当我在控制台中运行它时,我希望在记录“完成工作”之前完成所有工作:
await StartAttachedAsync(() =>
{
var result = Parallel.For(0, 4, async i =>
{
CallContext.LogicalSetData("ContextId", i);
await Task.Run(async () =>
{
await Task.Delay(2000);
await Task.Run(async () =>
{
await Task.Delay(2000);
Write("Step C done for i " + i);
});
Write("Step B done for i " + i);
});
Write("Step A done for i " + i);
});
Console.WriteLine("For is done: completed = " + result.IsCompleted);
});
Console.WriteLine("Jobs done");
private static async Task StartAttachedAsync(Action action)
{
await Task.Factory.StartNew(action,
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.Default);
}
给我:
For loop is done: completed = True
Jobs done
Step C done for i 0
Step C done for i 2
Step C done for i 3
Step C done for i 1
Step B done for i 1
Step A done for i 1
Step B done for i 0
Step A done for i 0
Step B done for i 3
Step A done for i 3
Step B done for i 2
Step A done for i 2
为什么在没有等待所有子任务的情况下完成循环?
答案 0 :(得分:1)
因为您使用异步方法执行Parallel.For作为未等待的正文。 所以基本上发生的事情是你在循环结构中启动火灾并忘记任务。
最好保留对您创建的任务的引用,然后执行 await Task.WhenAll(tasks);
你有什么理由使用Parallel.For
。你不能在没有它的情况下创建一堆任务吗?
在您当前的代码中,这样做:
await StartAttachedAsync(() =>
{
var tasks = new List<Task>();
var result = Parallel.For(0, 4, async i =>
{
CallContext.LogicalSetData("ContextId", i);
tasks.Add(Task.Run(async () =>
{
await Task.Delay(2000);
await Task.Run(async () =>
{
await Task.Delay(2000);
Write("Step C done for i " + i);
});
Write("Step B done for i " + i);
}));
Write("Step A done for i " + i);
});
await Task.WhenAll(tasks);
Console.WriteLine("For is done: completed = " + result.IsCompleted);
});