0

Can I assume the following code will always pass my assertions? I'm a worried about the index value. I'm not sure if the scoped value will be passed along to the Task.Run lambda expression. I think it will be scoped just like the attributesChunked value seems to be. But I'd like some confirmation.

var tasks = new List<Task>();
var attributes = new string[4]{ "att1", "att2", "att3", "att4" };
var chunkIndex = -1;
foreach (var attributesChunked in attributes.Chunk(2))
{
    var index = Interlocked.Increment(ref chunkIndex);
    tasks.Add(Task.Run(() =>
    {
        if (index == 0)
             Assert.Equal("attr1", attributesChunked.First());
        if (index == 2)
             Assert.Equal("attr3", attributesChunked.First());
    }
}
await Task.WhenAll(tasks);
Johan Donne
  • 3,104
  • 14
  • 21
Gary Brunton
  • 1,840
  • 1
  • 22
  • 33
  • 2
    you are using an index variable to check which chunk of attributes you are processing and this index variable is also scoped to each iteration of the loop and will be captured by the lambda expression in the same way as attributesChunked. therefore, your assertions should pass as expected. – 52414A Jun 02 '23 at 04:44

1 Answers1

2

For each task you create, you are introducing a closure on the index variable declared in that iteration. So yes your Task will use the right value, as can be tested using following code:

static async Task Main(string[] args)
{
    var tasks = new List<Task>();
    var attributes = new string[4] { "att1", "att2", "att3", "att4" };
    var chunkIndex = -1;
    foreach (var attributesChunked in attributes.Chunk(2))
    {
        var index = Interlocked.Increment(ref chunkIndex);
        tasks.Add(Task.Run(async () =>
        {
            //simulate some work...
            await Task.Delay(50);
            Console.WriteLine($"index: {index}");
        }));
    }
    await Task.WhenAll(tasks);
}

The result:

index: 0
index: 1

Note that the sequence of the output is entirely dependent on the scheduling of the individual Tasks and cannot be predicted...

Useful reference: What are 'closures' in .NET?

Johan Donne
  • 3,104
  • 14
  • 21