当前位置: 首页 > 编程语言 > C#

我可以等待我用生成器创建的可枚举吗?Share

时间:2023-04-10 19:18:13 C#

我可以等待我用生成器创建的可枚举吗?假设我有一个异步获取的整数序列。异步任务GetI(inti){returnawaitTask.Delay(1000).ContinueWith(x=>i);我想在那个序列上创建一个生成器,如果序列是同步的,我会这样做:IEnumerableMethod(){for(vari=0;i<100;i++){yieldreturnGetI(i);//不会工作,因为getI返回一个任务}}所以,我认为类比是让生成器异步并获得收益:asyncTaskMethod(){for(vari=0;ii);这是行不通的,因为带有yield的方法必须返回一个IEnumerable的东西,替代的,更有意义的是IEnumerable但不能编译,因为异步方法必须返回Tasks或void。现在,我意识到我可以简单地删除await并返回一个IEnumerable但这对我没有帮助,因为在任何数据准备好之前迭代一直在请求数据,所以它不能解决我的问题。(通过在线搜索,我怀疑第一个问题的答案是错误的,第二个问题是Observers/Observables,但我找不到任何关于以C#方式实现此模式的最佳规范参考)异步序列很有趣.有很多不同的方法,取决于你想做什么。我并不完全清楚你想要什么语义,所以这些是一些选择。Task>是一个异步检索的集合。只有一个任务——异步操作——检索整个集合。这听起来不像你想要的。IEnumerable>是(异步)数据的(同步)序列。有多个任务,可能会或可能不会同时处理。有几种选择可以实现这一点。一种是使用枚举器块和生成任务;每次从枚举中检索到下一个项目时,此方法都会启动一个新的异步操作。或者,您可以创建并返回一组同时运行的任务(这可以使用LINQ的Select后跟ToList/ToArray在源序列上优雅地完成)。然而,这也有一些缺点:无法异步确定序列是否已经结束,并且不容易在返回当前项后立即开始处理下一项(这通常是期望的行为)。核心问题是IEnumerable本质上是同步的。有几种解决方法。一个是IAsyncEnumerable,它是IEnumerable的异步等价物,在Ix-AsyncNuGet包中可用。然而,这种方法有其自身的缺点。当然,您失去了对IEnumerable的良好语言支持(即枚举器块和foreach)。此外,“异步可枚举”的概念并不完全符合要求;理想情况下,异步API应该厚而不繁琐,而枚举非常繁琐。这里有更多关于原始设计的讨论,以及粗略/讨厌的考虑。因此,如今更常见的解决方案是使用可观察对象或数据流(两者都可以通过NuGet获得)。在这些情况下,您必须将“序列”视为具有自己生命的事物。Observable是基于推送的,因此消费代码(理想情况下)是原生的。数据流具有参与者的感觉,因此它们更加独立,再次将结果推送到消费代码。您可以返回IEnumerable>:IEnumerable>Method(){for(vari=0;ii);}}并调用它:以上是C#学习教程:CanIwaitfortheenumerableIcreatedwiththegenerator?如果分享的内容对你有用,需要了解更多C#学习教程,希望你多多关注——foreach(variinMethod())Console.WriteLine(awaiti);本文收集自网络,并不代表侵权,如有侵权,请点击右边联系管理员删除。如需转载请注明出处: