【发布时间】:2020-08-18 10:53:35
【问题描述】:
我一直在重构我的项目中的一个常见模式,发现它并不像使用 LINQ Select 到异步函数那么简单。
对于上下文,这是当前的完成方式。
async Task<ICollection<Group>> ExecuteQueryGroupsForDomain(DomainInfo domain, int batchSize, CancellationToken ct)
{
try
{
return await BlahBlahActuallyGoGetGroupsForDomainHere(domain, batchSize, ct);
}
catch (Exception e)
{
return null;
}
}
var executeQueries = new List<Func<CancellationToken, Task<ICollection<Group>>>>();
domains.ForEach(domain =>
executeQueries.Add(async (ct) =>
await ExecuteQueryGroupsForDomain(domain, 123, ct)));
现在,如果我尝试使用 LINQ 替换 ForEach 循环部分:
var executeQueries = domains.Select(domain =>
async (ct) => await ExecuteQueryGroupsForDomain(domain, 123, ct));
它抱怨Type arguments cannot be inferred by the usage 这让我相信我没有从Select 返回任何东西,但我显然正在返回我想要的Func。
有没有更好的方法来创建Func 的列表,最好避免显式转换?还有什么解释为什么当Select'd async 方法清楚地告诉它应该是什么类型时编译器无法推断类型?
需要明确的是,我确实需要将CancellationToken 传递给Func,因为它与外部令牌不同(具体而言,它是将外部令牌与另一个内部令牌联系起来的链接令牌) .
【问题讨论】:
-
您真的要同时启动所有这些异步任务吗?
-
@JeremyLakeman 是的,每个任务都将通过网络相互独立地获取一些数据,服务器可以处理的远远超过我将简要介绍的并发负载。
-
@pinkfloydx33 试过了,同样的问题。我也尝试过没有任何取消令牌的外观,并且没有看到任何变化,因此令牌在这里没有影响。
-
domains.Select(async domain => await Execute(...))应该可以工作,但您会丢失 CT 参数。但是请看下面的答案。这有点小,但他是对的。无法推断类型,您需要明确 -
Also is there any explanation why the compiler is unable to infer the type when the Select'd async method is clearly telling it what the type should be?-Func和Action不是唯一的委托类型。可能有任意数量的委托类型与该签名匹配,这就是编译器不知道您想要哪一种的原因。