具有异步lambda和Task.WaitAll的Task.Factory.StartNew

时间:2015-06-13 14:36:13

标签: c# .net lambda async-await task-parallel-library

我正在尝试在任务列表中使用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操作?

4 个答案:

答案 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...
            });
        }
    }
}