有没有默认的方式来获取成功完成第一个任务? [英] Is there default way to get first task that finished successfully?

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

问题描述

让我们说,我有一对夫妇的任务:

Lets say that i have a couple of tasks:

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)+ ... + <$ C $ ç> K 任务。其中, N someInts.Count K 是位置在任务中第一次成功的任务,所以它的一切重新运行任务除了一个由WhenAny抓获。
那么,有没有什么办法让与运行的最大的 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 扩展方法是的 rel=\"nofollow\">我AsyncEx库;替代的实现也受到<一存在href=\"https://$c$cblog.jonskeet.uk/2012/01/16/eduasync-part-19-ordering-by-completion-ahead-of-time/\"相对=nofollow>乔恩斯基特和的斯蒂芬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.

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

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆