本文介绍了是否有默认方法来获得成功完成的第一个任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有几个任务:

void Sample(IEnumerable<int> someInts)
{
    var taskList = someInts.Select(x => DownloadSomeString(x));
}

async Task<string> DownloadSomeString(int x) {...}

我想获得第一个成功任务的结果.因此,基本的解决方案是编写如下内容:

I want to to get the result of first successful task. So, the basic solution is to write something like:

var taskList = someInts.Select(x => DownloadSomeString(x));
string content = string.Empty;
Task<string> firstOne = null;
while (string.IsNullOrWhiteSpace(content)){
    try
    {
        firstOne = await Task.WhenAny(taskList);
        if (firstOne.Status != TaskStatus.RanToCompletion)
        {
            taskList = taskList.Where(x => x != firstOne);
            continue;
        }
        content = await firstOne;
    }
    catch(...){taskList = taskList.Where(x => x != firstOne);}
}

但是这个解决方案似乎运行 N+(N-1)+..+K 任务.其中 NsomeInts.Count 并且 K 是任务中第一个成功任务的位置,因此它正在重新运行所有任务,除了被捕获的任务当任何.那么,有没有办法通过运行最多 N 个任务来获得第一个成功完成的任务?(如果任务成功则为最后一个)

But this solution seems to run N+(N-1)+..+K tasks. Where N is someInts.Count and K is position of first successful task in tasks, so as it's rerunning all task except one that is captured by WhenAny.So, is there any way to get first task that finished successfully with running maximum of N tasks? (if successful task will be the last one)

推荐答案

第一个成功的任务"的问题是如果所有任务都失败了怎么办? 这是一个有一个永远不会完成的任务真是个坏主意.

The problem with "the first successful task" is what to do if all tasks fail? It's a really bad idea to have a task that never completes.

我假设如果最后一个任务的异常全部失败,你会想要传播它们.考虑到这一点,我会说这样的话是合适的:

I assume you'd want to propagate the last task's exception if they all fail. With that in mind, I would say something like this would be appropriate:

async Task<Task<T>> FirstSuccessfulTask(IEnumerable<Task<T>> tasks)
{
  Task<T>[] ordered = tasks.OrderByCompletion();
  for (int i = 0; i != ordered.Length; ++i)
  {
    var task = ordered[i];
    try
    {
      await task.ConfigureAwait(false);
      return task;
    }
    catch
    {
      if (i == ordered.Length - 1)
        return task;
      continue;
    }
  }
  return null; // Never reached
}

此解决方案建立在 OrderByCompletion 扩展方法,即部分 我的 AsyncEx 库;乔恩斯基特Stephen Toub.

This solution builds on the OrderByCompletion extension method that is part of my AsyncEx library; alternative implementations also exist by Jon Skeet and Stephen Toub.

这篇关于是否有默认方法来获得成功完成的第一个任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 11:19