gpt4 book ai didi

c# - 异步返回集合的各种方式(具有 C# 7 特性)

转载 作者:太空狗 更新时间:2023-10-29 17:57:51 26 4
gpt4 key购买 nike

我有一个简单的同步方法,如下所示:

public IEnumerable<Foo> MyMethod(Source src)
{
// returns a List of Oof objects from a web service
var oofs = src.LoadOofsAsync().Result;
foreach(var oof in oofs)
{
// transforms an Oof object to a Foo object
yield return Transform(oof);
}
}

由于该方法是 Web 应用程序的一部分,因此最好尽可能有效地使用所有资源。因此,我想将方法​​更改为异步 方法。最简单的选择是做这样的事情:

public async Task<IEnumerable<Foo>> MyMethodAsync(Source src)
{
var oofs = await src.LoadOofsAsync();
return oofs.Select(oof => Transform(oof));
}

我都不是 async 的专家/awaitIEnumerable .然而,据我所知,使用这种方法“扼杀”了 IEnumerable 的好处。 ,因为在加载整个集合之前等待任务,因此省略了 IEnumerable 的“惰性”收藏。

在其他 StackOverflow 帖子中,我阅读了一些使用 Rx.NET 的建议(或 System.Reactive)。快速浏览我读过的文档 IObservable<T>是他们对 IEnumerable<T> 的异步替代.然而,使用天真的方法并尝试键入以下内容是行不通的:

public async IObservable<Foo> MyMethodReactive(Source src)
{
var oofs = await src.LoadOofsAsync();
foreach(var oof in oofs)
{
yield return Transform(oof);
}
}

我遇到一个编译错误,IObservable<T>没有实现 GetEnumerator() , 也不 GetAwaiter() - 因此它不能同时使用 yieldasync .我没有更深入地阅读 Rx.NET 的文档,所以我可能只是错误地使用了这个库。但是我不想花时间去学习一个新的框架去修改单一的方法。

有了新的possibilities in C# 7现在可以实现自定义类型。因此,理论上,我可以实现 IAsyncEnumerable ,这将同时定义 GetEnumerator()GetAwaiter()方法。但是,根据我以前的经验,我记得我曾尝试创建 GetEnumerator() 的自定义实现,但没有成功。 ...我最终得到了一个隐藏在容器中的简单列表。

因此我们有 4 种可能的方法来解决这个任务:

  1. 保持代码同步,但使用 IEnumerable
  2. 将其改为异步,但包装 IEnumerableTask<T>
  3. 学习和使用 Rx.NET (System.Reactive)
  4. 创建自定义 IAsyncEnumerable具有 C# 7 功能

每种尝试的优点和缺点是什么?其中哪一项对资源利用率的影响最显着?

最佳答案

  • Keep the code synchronous, but with IEnumerable
  • Change it to asynchronous, but wrap IEnumerable in a Task
  • Learn and use Rx.NET (System.Reactive)
  • Create a custom IAsyncEnumerable with C# 7 features

What are the benefits and drawbacks of each of these attempts? Which of them has the most significant impact on resource utilization?

在您的情况下,听起来最好的选择是 Task<IEnumerable<T>> .以下是每个选项的优点:

  1. 同步代码(或并行同步代码)在没有 I/O 但大量使用 CPU 时表现出色。如果您有同步等待的 I/O 代码(比如您的第一个方法实现),CPU 只会在等待 Web 服务响应时无所事事地燃烧周期。

  2. Task<IEnumerable<T>>适用于有 I/O 操作来获取集合的情况。运行等待 I/O 操作的线程可以在等待时安排其他事情。这听起来像你的情况。

  3. Rx 最适合推送场景:其中有数据被“推送”到您要响应的代码。常见示例是接收股票市场定价数据的应用程序或聊天应用程序。

  4. IAsyncEnumerable适用于当您有一个集合时,每个项目都需要或生成一个异步任务。一个例子:遍历一组项目并为每个项目执行某种独特的数据库查询。如果你的Transform实际上是 I/O 绑定(bind)异步方法,那么这可能更明智。

关于c# - 异步返回集合的各种方式(具有 C# 7 特性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45921385/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com