Task.WaitAny当有多个任务同时完成时

ptn*_*n77 5 c# parallel-processing task

我正在使用Task.WaitAny并传入正在运行的任务数组.如果有多个任务同时完成,我想知道如何捕获所有已完成任务的索引.

例如,我正在检索完成的任务的索引,如下所示:`

int i = Task.WaitAny(taskArray);
Run Code Online (Sandbox Code Playgroud)

使用索引i,我用另一个已启动的任务替换数组中的那个位置.taskArray具有固定长度,我只能在完成时启动新任务并替换数组中的任务.如果我只在Task.WaitAny()上返回一个索引,我怎么能这样做,并且阵列中的多个任务可能同时完成.如果只返回一个索引,我该如何处理同时完成的其他任务?

`

Pet*_*iho 6

如果只返回一个索引,我该如何处理同时完成的其他任务?

需要明确的是:对于所有意图和目的而言,不可能真正实现不止一项任务同时完成.即使同时在单独的CPU内核中运行,真正同时完成的可能性基本上也是零.

所以,你真正要问的是一个任务完成的竞争条件,然后WaitAny()在你的线程中调用返回并且调用方法中的后续代码可以执行之前,还完成一个或多个其他任务.

您的问题缺乏关于实际情况的详细信息,但通常您有几个选择:

  1. 扫描taskArray您传递给的人WaitAny(),查找当前已完成的所有任务.
  2. WaitAny()再次呼叫,除了您所知道的所有任务之前已经完成的所有任务.

哪个更合适取决于您实际需要对完成信息执行的操作.第一种选择最适用于您只关心当前完成的任务并希望立即处理它们的情况.第二种选择最适用于您对订购完成结果感兴趣的情况(即知道哪个任务以哪种顺序完成),但也希望立即继续等待剩余部分.

请注意,在第二个选项中,如果在WaitAny()再次调用之前完成了多个任务,则由于竞争条件,排序有些随意.条件由该WaitAny()方法"解决" ,选择哪个任务作为刚刚完成的当前任务呈现给您.但除非您在每项任务中保留自己的计时信息,否则您将无法确切知道哪些是真正完成的.

如果上述内容未能充分解决您的问题,则需要改进您的问题,以便它包含有关上述原因无法解决您的问题的完整详细信息,以及您尝试使用该WaitAny()方法的完整方式.确保包含一个良好的Minimal,Complete和Verifiable代码示例,说明了所有这些.


(旁白:上面当然都忽略了一个人是否应该使用WaitAny().异步等待使用通常会更好WhenAny().但同样的基本问题适用,并且不会改变答案,所以不担心这种差异似乎是合理的目前.)


Sir*_*ufo 3

任何任务都可以随时完成。当然,有可能同时完成两个或多个任务。

但就你的情况而言,没有什么是你应该关心的。Task.WhenAny将返回数组中已完成的一项任务的索引。在索引处放置一个新任务并Task.WhenAny再次调用。如果数组中有任何已完成的任务,它将立即返回已完成任务之一的索引。

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);
}
Run Code Online (Sandbox Code Playgroud)