I am testing the asynchronousity of C# async/await and came across a surprise where the subsequent code for ContinueWith does not wait for the previous task to complete:
public async Task<int> SampleAsyncMethodAsync(int number,string id)
{
Console.WriteLine($"Started work for {id}.{number}");
ConcurrentBag<int> abc = new ConcurrentBag<int>();
await Task.Run(() => { for (int count = 0; count < 30; count++) { Console.WriteLine($"[{id}] Run: {number}"); abc.Add(count); } });
Console.WriteLine($"Completed work for {id}.{number}");
return abc.Sum();
}
Which is executed with the below test method:
[Test]
public void TestAsyncWaitForPreviousTask()
{
for (int count = 0; count < 3; count++)
{
int scopeCount = count;
var c = SampleAsyncMethodAsync(0, scopeCount.ToString())
.ContinueWith((prevTask) =>
{
return SampleAsyncMethodAsync(1, scopeCount.ToString());
})
.ContinueWith((prevTask2) =>
{
return SampleAsyncMethodAsync(2, scopeCount.ToString());
});
}
}
The output shows execution for runs 0.0,1.0 and 2.0 executes asynchronously correctly but subsequent x.1 and x.2 get started almost immediately and x.2 actually completes before x.1. E.g. as logged below:
[2] Run: 0
[2] Run: 0
[2] Run: 0
Completed work for 2.0
Started work for 0.1
Started work for 0.2 <-- surprise!
[0] Run: 2
[0] Run: 2
[0] Run: 2
[0] Run: 2
[0] Run: 2
It seems the continueWith will only wait on the first task (0) regardless of subsequent chains. I can solve the problem by nesting the second ContinueWith within the first Continuewith block.
Is there something wrong with my code? I'm assuming Console.WriteLine respects FIFO.