C# 如何将Task.WhenAll()用于不同返回类型的多个列表?

C# 如何将Task.WhenAll()用于不同返回类型的多个列表?,c#,generics,async-await,task-parallel-library,task,C#,Generics,Async Await,Task Parallel Library,Task,我有两组任务,每个任务的结果类型不同: IEnumerable<Task<T1>> set1 = GetTasksOfT1(); IEnumerable<Task<T2>> set2 = GetTasksOfT2(); 这是因为如果我不使用铸造,我会出现以下错误: IEnumerable<Task<T1>>' does not contain a definition for 'Concat' and the best

我有两组任务,每个任务的结果类型不同:

IEnumerable<Task<T1>> set1 = GetTasksOfT1();
IEnumerable<Task<T2>> set2 = GetTasksOfT2();
这是因为如果我不使用铸造,我会出现以下错误:

IEnumerable<Task<T1>>' does not contain a definition for 'Concat' 
and the best extension method overload 'Queryable.Concat<Task<T2>>(IQueryable<Task<T2>>, IEnumerable<Task<T2>>)' 
requires a receiver of type 'IQueryable<Task<T2>>'

如果这两种方法,
GetTasksOfT1
GetTasksOfT2
都不会返回
Task
,而是
Task
,则不会有任何问题


因此,我建议重构这些方法以返回一系列任务对象,
IEnumerable
,或者选择Kote的解决方案。

实际上,编译器只是抱怨类型推断失败。你可以帮助它:

IEnumerable<Task<int>> set1 = null;
IEnumerable<Task<string>> set2 = null;

set1.Concat((IEnumerable<Task>)set2); //#1
((IEnumerable<Task>)set1).Concat(set2); //#2
set1.Concat<Task>(set2); //#3
IEnumerable set1=null;
IEnumerable set2=null;
set1.Concat((IEnumerable)set2)//#1.
(IEnumerable)set1.Concat(set2)//#2.
set1.Concat(set2)//#3.

提供类型信息还有许多其他方法。这是因为
IEnumerable
是协变的。这将调用
Enumerable.Concat(IEnumerable,IEnumerable)
如果您需要两组
任务的结果,那么不等待所有列表可能更简单

我想您的代码(使用usr的建议)应该是这样的:

IEnumerable<Task<T1>> set1 = GetTasksOfT1();
IEnumerable<Task<T2>> set2 = GetTasksOfT2();

await Task.WhenAll(set1.Concat<Task>(set2));

var t1Results = await Task.WhenAll(set1);
var t2Results = await Task.WhenAll(set2);
IEnumerable set1=GetTasksOfT1();
IEnumerable set2=GetTasksOfT2();
等待任务.WhenAll(set1.Concat(set2));
var t1Results=wait Task.WhenAll(set1);
var t2Results=等待任务WhenAll(set2);

但是在这里,组合的
wait
实际上没有任何用途。如果删除它,两个结果变量仍将正确初始化,因为它们都有自己的
wait
s.

尽管创建数组比串联两个可枚举数更好这一点值得商榷,但您可以将串联排除在等式之外:

await Task.WhenAll(set1, set2);
但是,由于您需要的是对每个任务序列的评估结果,因此我不会费心将它们作为一个集合来等待:

DoSomethingWithResults(await set1, await set2);

T1
T2
是否都遵循公共界面?@Clockwork Muse请查看我的编辑。但是,使用阻塞方法
Task.WaitAll()
是一个非常糟糕的建议。@Shay\uuuu-你是对的,这是一个糟糕的建议。不,我需要在任务完成后使用这些结果。回答得很好!我同意第三条:)
await Task.WhenAll(set1, set2);
DoSomethingWithResults(await set1, await set2);