Quote:
private static Task CreateNewTask( int index ) => new Task( async () =>
{
Console.WriteLine( $"Starting task {index}." );
await Task.Delay( TaskDelays[ index ] );
Console.WriteLine( $"Ending task {index}." );
});
This is the root of your problem.
The Task
constructor you're calling[
^] accepts an
Action
, not a
Func<Task>
. Your delegate returns after the first
await
call, at which point the parent
Task
has no idea that your delegate is still running. The parent
Task
completes immediately, but your delegate doesn't complete until after the specified delay.
Change your code to use
the Task.Run
method[
^] instead, and remove the loop which starts the tasks. You will then get the expected output in (more-or-less) the right order - eg:
private static Task CreateNewTask( int index ) => Task.Run( async () =>
{
Console.WriteLine( $"Starting task {index}." );
await Task.Delay( TaskDelays[ index ] );
Console.WriteLine( $"Ending task {index}." );
});
Console.WriteLine( "Create tasks" );
for( int i = 0; i < NumTasks; ++i )
_tasks.Add( CreateNewTask( i ) );
Console.WriteLine( "Await tasks" );
Console.WriteLine( TaskStatusString() );
await Task.WhenAll( _tasks );
****** START ******
Create tasks
Await tasks
Starting task 6.
Starting task 4.
Starting task 5.
Starting task 3.
Starting task 7.
Statuses: 0=WaitingForActivation; 1=WaitingForActivation; 2=WaitingForActivation; 3=WaitingForActivation; 4=WaitingForActivation; 5=WaitingForActivation; 6=WaitingForActivation; 7=WaitingForActivation; 8=WaitingForActivation; 9=WaitingForActivation;
Starting task 8.
Starting task 9.
Starting task 2.
Starting task 0.
Starting task 1.
Ending task 0.
Ending task 1.
Ending task 2.
Ending task 3.
Ending task 4.
Ending task 5.
Ending task 6.
Ending task 7.
Ending task 8.
Ending task 9.
After awaiting tasks
Statuses: 0=RanToCompletion; 1=RanToCompletion; 2=RanToCompletion; 3=RanToCompletion; 4=RanToCompletion; 5=RanToCompletion; 6=RanToCompletion; 7=RanToCompletion; 8=RanToCompletion; 9=RanToCompletion;
****** END ******
It would probably be a good idea to install
the Microsoft.VisualStudio.Threading.Analyzers
NuGet package[
^], which will add analyzers which would warn you about this pattern:
vs-threading/VSTHRD101.md at main · microsoft/vs-threading · GitHub[
^]