有没有一个通用的Task.WaitAll?(Is there a generic Task.Wait

2019-07-28 20:34发布

我开始几个并行任务,就像这样:

var tasks =
    Enumerable.Range(1, 500)
    .Select(i => Task.Factory.StartNew<int>(ProduceSomeMagicIntValue))
    .ToArray();

然后再加入他们

Task.WaitAll(tasks);

在这最后一行我得到下一个蓝色的波浪标志tasks ,一个警告消息:

  从任务[]共变体阵列转换到任务[]     可引起上写操作运行时异常。 

我明白为什么我得到这个消息,但有周围的办法吗? (例如,像仿制Task.WaitAll()

Answer 1:

我敢肯定,它甚至与预警安全运行,但如果你真的想要得到它周围比自己创建一个实现更好的选择是只为了你的转换tasks参数到它想要的类型:

Task.WaitAll(tasks.Cast<Task>().ToArray())

杀死蓝色的波浪线对我来说,让我保持我的tasks变量通用的,不逼我创造了一大堆新的可怕的代码是最终不必要的。



Answer 2:

Task.WaitAll的一般方法将意味着所有的任务必须要返回的将是极其有限的用途相同的类型。 书面方式类似的东西,可以手动完成(见巴斯Brekelmans答案),但是这不会允许ContinueWith或取消,无需大量的工作。

如果你不使用数组为别的是一个简单的解决方案

  .ToArray<Task>();


Answer 3:

您可以创建一个扩展方法来做到这一点。

我不知道了WaitAll的具体实现,但我们可以假设它等待每一个项目来完成:

static class TaskExtensions
{
    public static void WaitAll<T>(this Task<T>[] tasks)
    {
        foreach (var item in tasks)
        {
            item.Wait();
        }
    }
}

然后调用,从当前的代码:

tasks.WaitAll();

编辑

实际执行是更复杂一点。 我从这个答案省略了代码,因为它是相当长的。

http://pastebin.com/u30PmrdS

您可以修改此支持通用的任务。



Answer 4:

一个DIFFENENT答案

其实, 一个类似的泛型重载:

Task all = Task.WhenAll(tasks)

这是不同的在这个它返回一个Task完成所有任务后,将完成。 所以你可以使用await就可以了,或者Wait()任何你想要的。

看看签名:

重载

---------非GENERIC重载--------------

WhenAll(IEnumerable<Task>)创建一个任务,当所有的,将完成Task的枚举集合中的对象已经完成。

WhenAll(Task[])创建任务时所有的,将完成Task在一个阵列对象都已完成。

--------- GENERIC重载 --------------

WhenAll<TResult>(IEnumerable<Task<TResult>>)创建任务时所有的,将完成Task<TResult>的枚举集合中的对象已经完成。

WhenAll<TResult>(Task<TResult>[])创建任务时所有的,将完成Task<TResult>在阵列中的对象已完成。



文章来源: Is there a generic Task.WaitAll?