Task.WaitAny when there are multiple tasks that finish at the same time

I am using Task.WaitAny and passing to an array of running tasks. I would like to know how I can grab all indexes of completed tasks if multiple tasks were running at the same time.

For example, I retrieve the index of the task, which is done like this: `

int i = Task.WaitAny(taskArray);

      

Using index i, I replace that position in the array with another running task. The TaskArray is of a fixed length and I can start new tasks and replace the tasks in the array as they complete. How can I do this if I am only getting one index returned in Task.WaitAny () and it is possible that multiple tasks in the array might finish at the same time. If only one index is returned, how do I handle other tasks that complete at the same time?

`

+3


source to share


2 answers


If only one index is returned, how do I handle other tasks that complete at the same time?

To be clear: it is impossible to understand that it can literally be true, that more than one task will be completed at the same time. Even while running on separate processor cores at the same time, the probability of true concurrent completion is mostly zero.

So what you are really asking about is a race condition where one task completes and then, before your call WaitAny()

returns to your thread and subsequent code in the calling method might execute, one or more of the other tasks are complete as well.

Your question is missing details of your actual scenario, but usually you have several options:

  • Scan the taskArray

    one you uploaded to WaitAny()

    to see all currently completed tasks.
  • Call WaitAny()

    again, with all tasks previously transferred except those you know of.


More importantly, it depends on what you really need to do with the completion information. The first option is best when you only care about the tasks you are currently performing and want to get them done right away. The second option is best when you are interested in a custom completion result (i.e. know which task is completed in which order), but also want it to keep waiting for the rest.

Note that in the second option, if more than one task is completed before you call again WaitAny()

, the order is somewhat arbitrary due to a race condition. The condition is "solved" by the method WaitAny()

, where it chooses which task appears to you as the current task that has just completed. But if you don't store your own timing information for each task, you won't be able to know exactly what was actually completed in the first place.

If the above does not adequately address your problem, then you need to refine your question to include full details of why the above does not address your problem and exactly how you are trying to use completion WaitAny()

. Make sure you add a nice minimal, complete, and tested example code that illustrates all of this.


(Also, first of all, of course, it ignores whether or not to use at all WaitAny()

. It is generally best to wait asynchronously with help WhenAny()

. But the same basic problems apply and will not change the answer, so it seems reasonable not to worry about that difference for now. )

+5


source


Any task can be completed at any time. It is of course possible that two more tasks will be completed at the same time.

But in your case, you have nothing to worry about. Task.WhenAny

will return the index of one task into an array to be completed. Place the new task in the index and invoke it Task.WhenAny

again. If there were any completed tasks in the array, it will return without delay with the index of one of the completed tasks.



async Task Execute( IEnumerable<Func<Task>> taskFunctions, int maxParallel )
{
    var taskList = new List<Task>(maxParallel);
    foreach ( var taskFunc in taskFunctions )
    {
        var task = taskFunc();
        taskList.Add( task );
        if ( taskList.Count == maxParallel )
        {
            var idx = await Task.WhenAny( taskList ).ConfigureAwait(false);
            taskList.RemoveAt( idx );
        }
    }
    await Task.WhenAll( taskList ).ConfigureAwait(false);
}

      

+3


source







All Articles