如何在异步 C# 任务中使用 yield
How to use yield in async C# task
我正在尝试使用 yield 和 return 在异步任务中将 X 转换为 Y 的结果。但是,我在 select 上收到错误消息。
错误是:
Error CS1942 The type of the expression in the select clause is
incorrect. Type inference failed in the call to '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");
});
}
你没有。异步枚举支持(并且 yield 用于实现可枚举)在 2019 年的某个时候随 C# 8 一起出现。所以,现在的答案很简单,你不会。
你得到错误的原因是你也不能return一个结果。 Yield (return) 特定于实现枚举。您的方法签名不匹配。
简答:您不能使用异步 yield 语句。
但在大多数情况下,您不需要这样做。使用 LINQ
您可以在将所有任务传递到 Task.WaitAll
之前聚合所有任务。我将您的示例简化为 return 和 IEnumerable<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
创建待处理任务列表,return 通过调用函数 X
编辑。然后将等待并return编辑此任务列表。
这个workaround
应该适合大多数情况。 .Net 不支持真正的异步迭代器,例如 JavaScript。
更新:此功能当前建议作为语言提案:Async Streams。所以也许我们将来会看到这个。
更新:如果您需要异步迭代器,目前有几个选项可用:
- Reactive Stream,RX.Net,它为您提供基于事件的异步可观察流。
- 有异步迭代器或异步枚举的实现AsyncEnumerable或
.Net Async Enumerable
我正在尝试使用 yield 和 return 在异步任务中将 X 转换为 Y 的结果。但是,我在 select 上收到错误消息。 错误是:
Error CS1942 The type of the expression in the select clause is incorrect. Type inference failed in the call to '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");
});
}
你没有。异步枚举支持(并且 yield 用于实现可枚举)在 2019 年的某个时候随 C# 8 一起出现。所以,现在的答案很简单,你不会。
你得到错误的原因是你也不能return一个结果。 Yield (return) 特定于实现枚举。您的方法签名不匹配。
简答:您不能使用异步 yield 语句。
但在大多数情况下,您不需要这样做。使用 LINQ
您可以在将所有任务传递到 Task.WaitAll
之前聚合所有任务。我将您的示例简化为 return 和 IEnumerable<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
创建待处理任务列表,return 通过调用函数 X
编辑。然后将等待并return编辑此任务列表。
这个workaround
应该适合大多数情况。 .Net 不支持真正的异步迭代器,例如 JavaScript。
更新:此功能当前建议作为语言提案:Async Streams。所以也许我们将来会看到这个。
更新:如果您需要异步迭代器,目前有几个选项可用:
- Reactive Stream,RX.Net,它为您提供基于事件的异步可观察流。
- 有异步迭代器或异步枚举的实现AsyncEnumerable或 .Net Async Enumerable