首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >List<MyObject>不包含GetAwaiter的定义

List<MyObject>不包含GetAwaiter的定义
EN

Stack Overflow用户
提问于 2016-11-23 22:07:43
回答 3查看 57.7K关注 0票数 25

我有一个返回对象的List<>的方法。此方法需要一段时间才能运行。

代码语言:javascript
复制
private List<MyObject> GetBigList()
{
    ... slow stuff
}

此方法是从4或5个源调用的。因此,我想我应该尝试使用异步,并等待在这个列表构建时保持运行。我添加了这个方法:

代码语言:javascript
复制
public async Task<List<MyObject>> GetBigListAsync()
{
    var resultsTask = GetBigList();
    var resuls = await resultsTask;
    return resuls;
}

但是,在这条线上:

代码语言:javascript
复制
var resuls = await resultsTask;

我知道这个错误:

List不包含GetAwaiter的定义,也找不到接受List类型的第一个参数的扩展方法'GetAwaiter‘。

我遗漏了什么?

EN

回答 3

Stack Overflow用户

发布于 2016-11-28 08:16:44

看来你是个不成熟的人--等待。真正帮助我理解异步等待所做的是Eric在这次面试。搜索中给出的异步等待的餐厅类比。

在这里,他描述说,如果一个厨师必须等待什么,而不是什么都不做,他开始环顾四周,看看他是否可以在此期间做其他的事情。

异步等待类似。您的线程不会等待读取文件、返回数据库查询、下载网页,而是会在调用堆栈上查找是否有任何调用者正在等待,并执行这些语句直到他看到等待。一旦他看到等待线程再次上升调用堆栈,以查看其中一个调用者是否没有等待等等。过了一段时间,当文件被读取,或者查询完成等时,等待之后的语句将被执行。

通常,在阅读你的大名单时,你的帖子会很忙,而不是无所事事地等待。不确定的是,命令另一个线程来完成这些任务是否会增加阅读列表所需的时间。考虑测量这两种方法。

使用异步等待的一个原因,即使它会延长读取大列表所需的时间,也是为了保持调用者(用户界面?)有反应。

要使您的函数异步,您应该执行以下操作:

  • 声明函数异步;
  • 代替TResult返回Task<TResult>,代替void返回Task
  • 如果您的函数调用了其他异步函数,请考虑记住返回的任务而不是await,做其他您需要做的有用的事情,并在需要结果时对任务进行await
  • 如果你真的想让另一个线程来做那些繁忙的事情。打电话

Task.Run( () => GetBigList())

等待你需要的结果。

代码语言:javascript
复制
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写的,还有一些更高级的:异步-等待最佳实践

票数 40
EN

Stack Overflow用户

发布于 2016-11-23 22:11:39

resultTask只是从GetBigList()返回的列表,所以不会发生任何异步事件。

您可以通过使用Task.Run将任务卸载到线程池上的一个单独线程,并返回awaitable Task对象:

代码语言:javascript
复制
// Bad code
public Task<List<MyObject>> GetBigListAsync()
{
    return Task.Run(() => GetBigList());
}

虽然上面的例子最适合你想要做的事情,但这并不是最好的实践。尝试自然地使GetBigList()异步,或者如果真的没有办法,将在单独的线程上执行代码的决定留给调用代码,并且不要在实现F.e中隐藏这一点。如果调用代码已经运行异步,则没有理由生成另一个线程。这篇文章更详细地描述了这一点。

票数 18
EN

Stack Overflow用户

发布于 2020-06-02 22:35:03

几年后,但我觉得值得为这个集合添加一些内容,一旦人们搜索到分辨率,因为.NET已经发生了很大的变化:

return await Task.FromResult(GetBigList())

票数 16
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40774931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档