为了账号安全,请及时绑定邮箱和手机立即绑定

如何在异步 C# 任务中使用 yield

如何在异步 C# 任务中使用 yield

C#
呼啦一阵风 2021-11-28 19:31:56
我正在尝试使用 yield 并返回在异步任务中将 X 转换为 Y 的结果。但是,我在选择时遇到错误。错误是:错误 CS1942 select 子句中的表达式类型不正确。调用“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");        });    }
查看完整描述

2 回答

?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

简短回答:您不能使用异步 yield 语句。


但在大多数情况下,您不需要。使用LINQ您可以在将所有任务传递到Task.WaitAll. 我简化了您的示例以返回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用于创建挂起任务列表,通过调用函数返回X。然后将等待并返回此任务列表。


这workaround应该适合大多数情况。.Net 不支持真正的异步迭代器,例如在 JavaScript 中。


更新:目前建议将此功能作为语言建议:Async Streams。所以也许我们将来会看到这一点。


更新:如果您需要异步迭代器,目前有几个选项可用:

  1. Reactive Stream,RX.Net,它为您提供基于事件的异步可观察流。

  2. 有异步迭代器或异步可枚举的实现AsyncEnumerable或 .Net Async Enumerable


查看完整回答
反对 回复 2021-11-28
?
慕村9548890

TA贡献1884条经验 获得超4个赞

你不。2019 年的某个时间点,C# 8 提供了异步枚举支持(并且通过 yield 来实现可枚举)。所以,现在的答案很简单,你没有。

您收到错误的原因是您也无法返回结果。产量(回报)特定于实现枚举。您的方法签名不匹配。


查看完整回答
反对 回复 2021-11-28
  • 2 回答
  • 0 关注
  • 222 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信