sha*_*y__ 5 c# generics task task-parallel-library async-await
我有两组任务,每组都有不同的结果类型:
IEnumerable<Task<T1>> set1 = GetTasksOfT1();
IEnumerable<Task<T2>> set2 = GetTasksOfT2();
Run Code Online (Sandbox Code Playgroud)
现在我想在一行中等待两个集合,但我不得不用演员来投射 set1:
await Task.WhenAll(set1.Select(p => p as Task).Concat(set2));
Run Code Online (Sandbox Code Playgroud)
那是因为如果我不使用强制转换,我会收到此错误:
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>>'
Run Code Online (Sandbox Code Playgroud)
这是显而易见的。
那么有没有办法在不进行强制转换的情况下使用单个 WhenAll()?
编辑:返回类型 T1 和 T2很重要 - 我在等待任务后使用它们:
//After await Task.WhenAll(...):
var t1Results = await set1; // all set1 Tasks are completed by now
var t2Results = await set2; // same
DoSomethingWithResults(t1Results, t2Results);
Run Code Online (Sandbox Code Playgroud)
实际上,编译器只是抱怨类型推断失败。你可以帮助它:
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
Run Code Online (Sandbox Code Playgroud)
还有许多其他方法可以提供类型信息。这是有效的,因为它IEnumerable
是协变的。这将调用Enumerable.Concat<Task>(IEnumerable<Task>, IEnumerable<Task>)
.