我有一个返回对象的List<>的方法。此方法需要一段时间才能运行。
private List<MyObject> GetBigList()
{
... slow stuff
}此方法是从4或5个源调用的。因此,我想我应该尝试使用异步,并等待在这个列表构建时保持运行。我添加了这个方法:
public async Task<List<MyObject>> GetBigListAsync()
{
var resultsTask = GetBigList();
var resuls = await resultsTask;
return resuls;
}但是,在这条线上:
var resuls = await resultsTask;我知道这个错误:
List不包含GetAwaiter的定义,也找不到接受List类型的第一个参数的扩展方法'GetAwaiter‘。
我遗漏了什么?
发布于 2016-11-28 08:16:44
看来你是个不成熟的人--等待。真正帮助我理解异步等待所做的是Eric在这次面试。搜索中给出的异步等待的餐厅类比。
在这里,他描述说,如果一个厨师必须等待什么,而不是什么都不做,他开始环顾四周,看看他是否可以在此期间做其他的事情。
异步等待类似。您的线程不会等待读取文件、返回数据库查询、下载网页,而是会在调用堆栈上查找是否有任何调用者正在等待,并执行这些语句直到他看到等待。一旦他看到等待线程再次上升调用堆栈,以查看其中一个调用者是否没有等待等等。过了一段时间,当文件被读取,或者查询完成等时,等待之后的语句将被执行。
通常,在阅读你的大名单时,你的帖子会很忙,而不是无所事事地等待。不确定的是,命令另一个线程来完成这些任务是否会增加阅读列表所需的时间。考虑测量这两种方法。
使用异步等待的一个原因,即使它会延长读取大列表所需的时间,也是为了保持调用者(用户界面?)有反应。
要使您的函数异步,您应该执行以下操作:
TResult返回Task<TResult>,代替void返回Task;await,做其他您需要做的有用的事情,并在需要结果时对任务进行await;Task.Run( () => GetBigList())
等待你需要的结果。
private async Task<List<MyObject>> GetBigListAsync()
{
var myTask = Task.Run( () => GetBigList());
// your thread is free to do other useful stuff right nw
DoOtherUsefulStuff();
// after a while you need the result, await for myTask:
List<MyObject> result = await myTask;
// you can now use the results of loading:
ProcessResult(result);
return result;
}再一次:如果在其他线程加载列表时没有什么有用的操作(比如保持UI响应),就不要这样做,或者至少测量一下是否更快。
其他帮助我理解异步等待的文章有:异步等待,由Stephen写的,还有一些更高级的:异步-等待最佳实践。
发布于 2016-11-23 22:11:39
resultTask只是从GetBigList()返回的列表,所以不会发生任何异步事件。
您可以通过使用Task.Run将任务卸载到线程池上的一个单独线程,并返回awaitable Task对象:
// Bad code
public Task<List<MyObject>> GetBigListAsync()
{
return Task.Run(() => GetBigList());
}虽然上面的例子最适合你想要做的事情,但这并不是最好的实践。尝试自然地使GetBigList()异步,或者如果真的没有办法,将在单独的线程上执行代码的决定留给调用代码,并且不要在实现F.e中隐藏这一点。如果调用代码已经运行异步,则没有理由生成另一个线程。这篇文章更详细地描述了这一点。
发布于 2020-06-02 22:35:03
几年后,但我觉得值得为这个集合添加一些内容,一旦人们搜索到分辨率,因为.NET已经发生了很大的变化:
return await Task.FromResult(GetBigList())
https://stackoverflow.com/questions/40774931
复制相似问题