我正在尝试使用yield并在异步任务中返回将X转换为Y的结果。但是,我在选择时遇到错误。 错误是:
错误CS1942 select子句中的表达式类型为 不正确调用“选择”时类型推断失败。
public async Task<Result<dynamic>> GetYAsync(IEnumerable<X> infos)
{
return Task.WhenAll(from info in infos.ToArray() select async ()=>
{
yield return await new Y(info.Id, "Start");
});
}
答案 0 :(得分:6)
简短的回答:您不能使用异步yield语句。
但是在大多数情况下,您不需要这样做。使用LINQ
,您可以先汇总所有任务,然后再将其传递到Task.WaitAll
。我简化了您的示例以返回IEnumberable<int>
,但这适用于每种类型。
public class Program
{
public static Task<int> X(int x) {
return Task.FromResult(x);
}
public static async Task<IEnumerable<int>> GetYAsync(IEnumerable<int> infos)
{
var res = await Task.WhenAll(infos.Select(info => X(info)));
return res;
}
public static async void Main()
{
var test = await GetYAsync(new [] {1, 2, 3});
Console.WriteLine(test) ;
}
}
您的示例还有另一个错误await new Y(...)
,构造函数不能异步,因此我将其替换为异步函数。 (正如评论中所暗示的那样,从技术上讲,可以创建一个自定义的等待类型并使用new
来创建此类型,尽管很少使用),
以上示例使用infos.Select
创建了待处理任务的列表,这些任务是通过调用函数X
返回的。然后将等待并返回此任务列表。
此workaround
应该适合大多数情况。 .Net不支持真正的异步迭代器,例如JavaScript。
更新:当前建议将此功能作为语言建议:Async Streams。因此,也许将来我们会看到这种情况。
更新:如果您需要异步迭代器,则当前有一些可用选项:
答案 1 :(得分:3)
您没有。看起来C#8在2019年的某个时候附带了异步枚举支持(并且可以实现可枚举的收益率)。因此,目前的答案很简单,就是您不知道。
出现错误的原因是您也无法返回结果。收益(回报)特定于实现枚举。您的方法签名不匹配。