Task.WhenAny
will return the first task which completed. You can use that to remove it from the list.
while (!gotSuccess && _tasks.Count != 0)
{
Task<bool> completedTask = await Task.WhenAny(_tasks);
_tasks.Remove(completedTask);
++numCompletedTasks;
if (await completedTask)
{
Debug.WriteLine( $"Task successfully connected; number of completed tasks = {numCompletedTasks}." );
gotSuccess = true;
}
}
If you want to cancel the other tasks once one task has succeeded, then a
CancellationToken
is the correct approach:
private static async Task<bool> ReturnDelayedResultAsync( int index, CancellationToken cancellationToken )
{
Debug.WriteLine( $"Starting task {index}." );
await Task.Delay( TaskDelays[ index ], cancellationToken );
Debug.WriteLine( $"Ending task {index}." );
return index == 6;
}
private static async Task RunAsync()
{
CancellationTokenSource cts = new();
for( int i = 0; i < NumTasks; ++i )
_tasks.Add( ReturnDelayedResultAsync( i, cts.Token ) );
int numCompletedTasks = 0;
bool gotSuccess = false;
while( !gotSuccess && _tasks.Count != 0 )
{
Debug.WriteLine( $"Awaiting {_tasks.Count} tasks" + TaskStatusString() );
Task<bool> completedTask = await Task.WhenAny(_tasks);
_tasks.Remove(completedTask);
++numCompletedTasks;
if (await completedTask)
{
Debug.WriteLine( $"Task successfully connected; number of completed tasks = {numCompletedTasks}." );
gotSuccess = true;
cts.Cancel();
}
}
}