我正在尝试在任务列表中使用Task.WaitAll
。事情是任务是一个异步lambda,它打破Tasks.WaitAll
,因为它永远不会等待。
以下是一个示例代码块:
List<Task> tasks = new List<Task>();
tasks.Add(Task.Factory.StartNew(async () =>
{
using (dbContext = new DatabaseContext())
{
var records = await dbContext.Where(r => r.Id = 100).ToListAsync();
//do long cpu process here...
}
}
Task.WaitAll(tasks);
//do more stuff here
由于异步lambda,因此不会等待。那我该如何等待我的lambda中的I / O操作?
答案 0 :(得分:17)
由于异步lambda,这不会等待。那么我该怎么做呢 等待我的lambda中的I / O操作?
Task.WaitAll
等待异步lambda提供的IO工作完成的原因是因为Task.Factory.StartNew
实际返回Task<Task>
。由于您的列表是List<Task>
(而Task<T>
派生自Task
),因此等待StartNew
开始的外部任务,而忽略内部任务由异步lambda创建。这就是为什么他们说Task.Factory.StartNew
对于异步来说是危险的。
你怎么能解决这个问题?您可以显式调用Task<Task>.Unwrap()
以获取内部任务:
List<Task> tasks = new List<Task>();
tasks.Add(Task.Factory.StartNew(async () =>
{
using (dbContext = new DatabaseContext())
{
var records = await dbContext.Where(r => r.Id = 100).ToListAsync();
//do long cpu process here...
}
}).Unwrap());
或者像其他人说的那样,你可以打电话给Task.Run
:
tasks.Add(Task.Run(async () => /* lambda */);
此外,既然你想做正确的事情,你就会想要使用Task.WhenAll
,为什么是异步等待,而不是同步阻止的Task.WaitAll
:
await Task.WhenAll(tasks);
答案 1 :(得分:15)
Task.Factory.StartNew
无法识别async
个委托,因为没有重载接受返回Task
的函数。
这还有其他原因(请参阅StartNew is dangerous),这就是您应该在Task.Run
使用{<1}}的原因:
tasks.Add(Task.Run(async () => ...
答案 2 :(得分:0)
你可以这样做。
void Something()
{
List<Task> tasks = new List<Task>();
tasks.Add(ReadAsync());
Task.WaitAll(tasks.ToArray());
}
async Task ReadAsync() {
using (dbContext = new DatabaseContext())
{
var records = await dbContext.Where(r => r.Id = 100).ToListAsync();
//do long cpu process here...
}
}
答案 3 :(得分:-2)
您必须使用Task.ContinueWith
方法。喜欢这个
List<Task> tasks = new List<Task>();
tasks.Add(Task.Factory.StartNew(() =>
{
using (dbContext = new DatabaseContext())
{
return dbContext.Where(r => r.Id = 100).ToListAsync().ContinueWith(t =>
{
var records = t.Result;
// do long cpu process here...
});
}
}
}