【问题标题】:How do I asynchronously enumerate a collection in an ASP.NET environment?如何在 ASP.NET 环境中异步枚举集合?
【发布时间】:2016-11-12 14:34:24
【问题描述】:

我的环境是 ASP.NET Core 和 EF Core。我需要在请求期间异步“分页”实体集合。

所以我创建了这个集合类:

public class PagedList<T> : IEnumerable<T> { /* ... */ }

还有这个异步枚举的扩展方法:

public static async Task<PagedList<T>> ToPagedListAsync<T>(this IQueryable<T> items, int pageSize, int pageNumber) {
    return await Task.Run(() => new PagedList<T>(items, pageSize, pageNumber));
}

现在我可以这样做了:

var stuff = await repository.CreateQueryableForLoadingStuff().ToPagedListAsync(10, 1);

我查看了source for EF's ToListAsync() 以获得指导——它不只是像我所做的那样包装同步操作,而是直接异步枚举到一个新集合中。 I also saw this 解释了 FooAsync() 方法如果使用 Task.Run() 启动一个新线程就不是“真正的”异步,并且由于我在 ASP.NET 请求中操作,这可能是错误的方法。

我的方法是否适合我的环境(ASP.NET Core 和 EF Core),还是应该使用该链接中的方法?另外,我应该使用.ConfigureAwait(false)吗?

【问题讨论】:

  • 这对于 ASP.NET 来说是一种糟糕的技术。您所做的只是创建一个线程。每个 ASP.NET 请求都已在线程池线程上发生。为什么要创建一个额外的线程?此外,从您的示例中很难看出,但看起来您几乎打算在 C# 中进行分页?为什么不让数据库来做呢?这将大大提高效率。如果你只想要 10 行,不要全部返回 10000 然后选择前 10 行,只需使用 SkipTake 来获取你需要的结果。
  • @dman2306 PagedList 类使用 EF 的 SkipTake 对数据库进行分页。这是我关心的异步枚举。那么,如果它对 ASP.NET 不利,我应该怎么做呢?
  • 你想做一些像 EF 一样的事情。目标是使 I/O 异步。这意味着,当您等待套接字读取数据时,您希望 ASP.NET 请求线程在操作系统等待 IO 时不使用时返回到线程池。
  • @dman2306 请添加第二条评论作为答案,以便我接受。

标签: c# asp.net entity-framework linq async-await


【解决方案1】:

我认为您放错了异步组件。您想要 I/O 部分(EF/Repository)上的异步,而不是内存中的部分(PagedList),那么如何改为:

public static PagedList<T> ToPagedList<T>(this IQueryable<T> items, int pageSize, int pageNumber) {
    return new PagedList<T>(items, pageSize, pageNumber);
}

那么你就可以这样做了……

var stuff = (await repository.CreateQueryableForLoadingStuffAsync()).ToPagedList(10, 1);

...这与您最初的意图仅相差几个括号。

编辑:就像在 cmets 中一样,这不会让您有效地使用可查询对象来约束 SQL 查询,并且您将在内存中进行分页。作为使可查询工作有效的替代方法,请查看PagedList and Async

【讨论】:

  • 我认为这只是一个错字。但这不是真正的问题 - 这不是语法问题。这是关于在 ASP.NET 环境中将枚举卸载到新线程还是异步枚举到新集合中更好。
  • 同样这种方法会拉下整个表,然后在内存中执行分页。而我的 PagedList 类发出 SkipTake 如上所述,因此它需要成为异步操作的一部分。
  • 是的,但是 PagedList 构造函数采用 IQueryable,而不是 Task,所以如果你想使用它们,你似乎有点卡在那里。我添加了一个带有指向另一个选项的链接的编辑。
  • 我的分页是在数据库上完成的。我正在使用类似于您链接到的库的东西。上面的评论是对的,就是我发的东西不好。我最终几乎完全按照他们在 EF 的异步方法中所做的工作。
  • 如果您现在有一个很好的答案(最好有一些代码),那么值得将其发布为您自己问题的答案,这样以后遇到相同问题的任何人如果发现该问题都知道要解决它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2017-11-22
  • 2011-01-20
相关资源
最近更新 更多