Cri*_*scu 60 c# generics covariance task-parallel-library
我启动了一些并行任务,如下所示:
var tasks =
Enumerable.Range(1, 500)
.Select(i => Task.Factory.StartNew<int>(ProduceSomeMagicIntValue))
.ToArray();
Run Code Online (Sandbox Code Playgroud)
然后加入他们
Task.WaitAll(tasks);
Run Code Online (Sandbox Code Playgroud)
在最后一行,我得到一个蓝色波浪形标记tasks
,并带有警告信息:
__PRE__
我理解为什么我会收到这条消息,但有没有办法解决这个问题呢?(例如,像通用版本Task.WaitAll()
?)
Mer*_*OWA 28
Task.WaitAll的一般方法意味着所有任务都必须返回相同的类型,这种类型的用处非常有限.写这样的东西可以手动完成(参见Bas Brekelmans的答案),但这不允许ContinueWith或取消没有很多工作.
一个简单的解决方案,如果你没有使用该数组的其他任何东西是
.ToArray<Task>();
Run Code Online (Sandbox Code Playgroud)
DMa*_*yer 28
我很确定这是一个安全的操作,即使有警告,但如果你真的想绕过它比创建自己的实现更好的选择只是将你的tasks
参数转换为它想要的类型:
Task.WaitAll(tasks.Cast<Task>().ToArray())
Run Code Online (Sandbox Code Playgroud)
为我杀死了蓝色的波浪线,让我保持我的tasks
变量通用,并没有强迫我创建一大堆新的可怕代码,这些代码最终是不必要的.
您可以创建一个扩展方法来执行此操作.
我不知道WaitAll的确切实现,但我们可以假设它等待每个项目完成:
static class TaskExtensions
{
public static void WaitAll<T>(this Task<T>[] tasks)
{
foreach (var item in tasks)
{
item.Wait();
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后从您当前的代码中调用:
tasks.WaitAll();
Run Code Online (Sandbox Code Playgroud)
编辑
实际实现有点复杂.我已经省略了这个答案的代码,因为它相当长.
您可以修改它以支持通用任务.
其实有IS仿制出类似超载:
Task all = Task.WhenAll(tasks)
Run Code Online (Sandbox Code Playgroud)
这是不同的,它返回一个Task
将在所有任务完成后完成的操作。因此您可以随便await
在其上使用,或Wait()
。
看一下签名:
超载
---------非常规过载--------------
WhenAll(IEnumerable<Task>)
创建一个将Task
在可枚举集合中的所有对象均完成后完成的任务。
WhenAll(Task[])
创建一个任务,该任务将Task
在数组中的所有 对象均已完成时完成。---------一般超载 --------------
WhenAll<TResult>(IEnumerable<Task<TResult>>)
创建一个将Task<TResult>
在可枚举集合中的所有对象均完成后完成的任务。
WhenAll<TResult>(Task<TResult>[])
创建一个任务,该任务将Task<TResult>
在数组中的所有对象均已完成时完成。
归档时间: |
|
查看次数: |
9814 次 |
最近记录: |