IQueryable 和 IQueryable<T> 是异步的吗?
Posted
技术标签:
【中文标题】IQueryable 和 IQueryable<T> 是异步的吗?【英文标题】:Are IQueryable and IQueryable<T> async? 【发布时间】:2019-04-24 08:35:23 【问题描述】:接口IQueryable
和IQueryable<T>
是异步的吗?
我的意思是,假设以下代码:
void Method()
var customers = CustomerReposity.ToQueryable(); //The execution of query starts here.
DoSomething();
foreach (var customer in customers) // The foreach await to finish
customer.DoSomething();
我的猜测对吗?如果不是,实现异步行为的正确形式是什么?
也许……
async void Method()
var customers = CustomerReposity.ToQueryable().ToListAsync(); //The execution of query starts here.
DoSomething();
foreach (var customer in await customers) // The foreach await to finish
customer.DoSomething();
这是个好主意吗?
【问题讨论】:
这个问题好像是:什么时候使用异步方法? @TânNguyễn 不,我知道什么时候使用异步,问题是 IQueryable 接口是否默认是异步的。IQueryable
与async
无关。 ToListAsync
只是使用异步任务将项目转换为列表的扩展方法(需要await
)。
除了Tan的回复,IQueryable
更像,你需要的时候我给你,或者延迟加载。我什至不会打扰您的第一个代码块async-ing。
@TânNguyễn 当我调用IQueryable.ToListAsync()
时开始执行查询?因为在我使用 foreach 之前查询是并行运行的,所以在 foreach 上等待它是一个好主意吗? DoSomething()
方法可以长时间运行。
【参考方案1】:
不,IQueryable
和 IQueryable<T>
不是异步的,也不需要异步。这两个接口提供了从源中提取一些数据的方法,但由源提供异步支持。如果源将返回内存中的所有数据,那么异步使用它是没有意义的。但是,如果源是从网络“流式传输”的,那么异步枚举它可能是有意义的。
【讨论】:
更准确地说,接口(和接口成员定义)不能是异步的。接口成员的实现可以是,只要其实现的方法满足为async
方法的要求(如返回Task
或Task<T>
)。
更准确地说,只有 方法 可以是异步的。 :-)
好的,我认为我的问题是错误的。我知道IQueryable
推迟执行查询,直到它被转换或在 foreach 中使用。我的问题是,如果检索数据源是一个长时间运行的过程(如数据库连接),如果我在 foreach 中使用IQueryable
或IQueryable<T>
,线程会被阻塞直到我得到结果?我可以在 foreach 中使用它之前异步启动查询执行吗?在 foreach 中使用之前调用 IQueryable.ToAsyncEnumerable()
或 IQueryable.ToListAsync()
是否是启动查询执行的正确方法?
await xxx.ToListAsync()
将使您的查询异步执行,即等待此方法将导致您的线程返回线程池并可以运行其他内容,直到查询执行并返回结果到数据库。您的代码foreach (var customer in await customers)
正是这样做的。所以是的,这是正确的做法。
是的,当你调用xxx.ToListAsync()
而不等待它时,查询执行开始,你可以做其他事情。是的,DoSomething()
将在查询在后台执行时并行执行。以上是关于IQueryable 和 IQueryable<T> 是异步的吗?的主要内容,如果未能解决你的问题,请参考以下文章
IQueryable和IEnumerable以及AsEnumerable()和ToList()的区别