Two tasks start even if there is only one item using async / wait and Task.WhenAll

What happened to my code here? Even if item.count is only 1, the DoSomething method is called twice, and the counter is 2. Have I really structured the waiters correctly, or am I using WhenAll incorrectly?

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;
     } 
+4
source share
1 answer

You are using it Selectwrong, basically. This is lazy, remember? So every time you iterate over it (once for Count()and once in WhenAll) ... it will call your delegate again.

The fix is ​​simple: just materialize the request, for example. with ToList():

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

. , tasks.Count() , Count. - Any():

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

( , , ...)

+13

All Articles