【问题标题】:How would you correctly return a collection of objects asynchronously? [closed]您将如何正确地异步返回对象集合? [关闭]
【发布时间】:2015-10-22 06:44:43
【问题描述】:

我需要在我的核心接口中定义返回列表的方法。我的项目严重依赖 async/await 的使用,因此我需要将我的核心引用/接口定义为尽可能异步。我还将 EF7 用于我的数据访问层。我目前在任何地方都使用IAsyncEnumerable

我目前正在决定是继续使用IAsyncEnumerable 还是恢复使用Task<IEnumerable<T>>IAsyncEnumerable 在这一点上似乎很有希望。 EF7 也是using。问题是,我不知道也无法弄清楚如何使用它。 website 上几乎没有任何内容告诉任何人如何使用 Ix.Net。我可以在IEnumerable 对象上使用ToAsyncEnumerable 扩展,但这不会异步执行任何操作(或者是吗??)。另一个缺点是给定以下签名:

IAsyncEnumerable GetPersons();

因为这不是一个返回Task的函数,所以我不能在函数块内使用async/await。

另一方面,我的直觉告诉我应该坚持使用Task<IEnumerable<T>>。这当然也有它的问题。 EF 没有返回此类型的扩展方法。它有一个ToArrayAsyncToListAsync 扩展方法,但这当然需要你在方法内部调用await,因为Task<T> 不是协变的。这可能是一个问题,因为这会创建一个额外的 操作,如果我简单地返回 Task 对象,就可以避免这种情况。

我的问题是:我应该继续使用IAsyncEnumerable(首选)还是应该将所有内容改回Task<IEnumerable<T>>(不首选)?我也愿意接受其他建议。

【问题讨论】:

  • 您似乎了解每个选项的缺点。剩下的就是意见。我的在 IAsyncEnumerable 一边。
  • 谢谢。你能用为什么你认为它是更好的选择来支持它吗?
  • 因为它是惰性和异步的。这就是未来。
  • 我同意它是懒惰的,这就是我喜欢它的地方。你有什么可以帮助我学习如何使用它的吗?
  • 试错?这都是新东西。您可以克隆他们的代码并在其中查看哪些操作可用...

标签: c# .net async-await system.reactive entity-framework-core


【解决方案1】:

我会选择IAsyncEnumerable。它可以让您的操作保持异步和惰性。

没有它,您需要返回Task<IEnumerble>,这意味着您正在将所有结果加载到内存中。在许多情况下,这意味着查询和持有比需要更多的内存。

经典案例是用户调用Any 的查询。如果是Task<IEnumerable>,它会先将所有结果加载到内存中,如果是IAsyncEnumerable,加载一个结果就足够了。

同样相关的是,使用Task<IEnumerable>,您需要将整个结果集同时保存在内存中,而使用IAsyncEnumerable,您可以一次“流式传输”几个结果。

此外,这也是生态系统的发展方向。它是通过响应式扩展添加的,就在本周由new library suggested by Stephen Toub 添加,并且可能是supported in the next version of C# natively

【讨论】:

  • IAsyncEnumerable 成为champion 已有一段时间了。希望它能在 C# 8 中实现。
【解决方案2】:

您应该只使用Task<IEnumerable<T>> 返回类型。原因很简单,您不想针对要读取的 每个 对象懒惰地对数据库运行新查询,因此只需让 EF 一次查询这些对象,然后传递该集合。

当然你可以把异步列表变成一个异步枚举,但何必呢。一旦您将数据存储在内存中,就没有理由人为地延迟对它的访问。

【讨论】:

  • 谢谢。您建议最好的方法是使用 EF 而不使用 await 返回 Task<IEnumerable<T>>
  • 你为什么不想使用await?就做await return someEfLinqQuery.ToListAsync()
  • 因为它会创建不必要的异步操作,尤其是当您不需要等待函数内的任何内容时,当然除了 .ToListAsync 之外。
  • 异步操作已经在运行,但是是的,它创建了另一个异步上下文。但是return await Something() 比只返回原始任务要好,因为这将确保异常被封装在任务中(并且不会立即抛出)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
相关资源
最近更新 更多