即使只有一个项目,使用async / await和Task.WhenAll,两个任务也会被触发

时间:2014-08-07 20:11:41

标签: c# .net asynchronous async-await task

我的代码出了什么问题?即使items.count只有1,DoSomething方法也会被调用两次,计数器等于2.我是否没有正确构造等待或我是否错误地使用了WhenAll?

public async Task<int> Process(string id)
    {
        var items = await GetItemsAsync(id);
        var counter = 0;

        var tasks = items.Select(async item =>
            {
                if (await DoSomething(item))
                    counter++
            });

            if (tasks.Count() > 0)
                await Task.WhenAll(tasks);

        return counter;
     } 

1 个答案:

答案 0 :(得分:13)

您基本上错误地使用Select。它很懒,还记得吗?所以每次你迭代它(一次为Count()而一次在WhenAll)......它会再次给你的代表打电话。

修复很简单:只需实现查询,例如与ToList()

var tasks = items.Select(async item =>
{
    if (await DoSomething(item))
    {
        counter++
    }
}).ToList();

这样就可以创建一次的任务。实际上,tasks.Count()现在根本不需要迭代,因为它已经过优化以使用Count属性。但我仍然使用Any()代替:

if (tasks.Any())
{
    await Task.WhenAll(tasks);
}

(顺便说一下,我强烈建议总是使用大括号。它更具有抗虫性......)