Post

C# Tasks Unexpectedly Running More Than Once (Async Lambda IEnumerable<Task> With foreach Loop)

Consider the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
using System.Linq;
using System.Threading.Tasks;
                    
public class Program
{
    public static async Task Main()
    {
        var items = new[] { "a", "b", "c", "d", "e" };

        var tasks = items.Select(async item =>
        {
            Console.WriteLine(item);
            await Task.Delay(1);
        })
        // One method to fix:
        // .ToList()
        ;
            
        await Task.WhenAll(tasks);
            
        foreach (var task in tasks)
        {
            // The Console.WriteLine(item); to print the item runs again
            Console.WriteLine(task.Id);
        }
    }
}

What’s happening?

The tasks are being constructed twice, once in the LINQ Select and once in the foreach loop.

We can fix this by calling ToList() on the IEnumeable<Task> returned by the LINQ Select.

Hope that helps!

This post is licensed under CC BY 4.0 by the author.