What's wrong with my code here? Even when items.count is only 1, the DoSomething method gets called twice, and counter is equal to 2. Have I not structured the awaits correctly or am I using the 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;
}
You're using Select
incorrectly, basically. It's lazy, remember? So every time you iterate over it (once for Count()
and once in WhenAll
)... it's going to call your delegate again.
The fix is simple: just materialize the query, e.g. with ToList()
:
var tasks = items.Select(async item =>
{
if (await DoSomething(item))
{
counter++
}
}).ToList();
That way you create the tasks once. In fact, tasks.Count()
doesn't need to iterate at all now, as it's optimized to use the Count
property. But I'd still use Any()
instead:
if (tasks.Any())
{
await Task.WhenAll(tasks);
}
(I'd strongly advise always using braces, by the way. It's much more bug-resistant...)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With