2016-11-23 46 views
5

我有一个方法返回一个对象的列表<>。此方法需要一段时间才能运行。列表<MyObject>不包含GetAwaiter的定义

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<MyObject> does not contain a definition for GetAwaiter, and no extension method 'GetAwaiter' accepting a first argument of type List<MyObject> could be found.

我缺少什么?

+1

你的示例代码没有显示出任何使用任务的GetBigList方法也不会标记为async,这意味着不能等待该方法的结果。 –

+0

尝试异步任务<列表> GetBigList() – Mate

+2

请记住,await不会将异步操作转换为异步操作。等待将当前方法的其余部分注册为*已有的*异步操作的继续。等待是关于*管理异步*,而不是*创建*。如果你希望同步操作是异步的,你将不得不找出一种方法来实现这一点。 –

回答

9

resultTask只是从GetBigList()返回的列表,所以在那里没有任何异步发生。

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

// Bad code 
public Task<List<MyObject>> GetBigListAsync() 
{ 
    return Task.Run(() => GetBigList()); 
} 

虽然上面的例子最符合你正在尝试做的,它是不是最佳实践。尝试使GetBigList()本质上是异步的,或者如果真的没有办法,就把执行代码的决定放在一个单独的线程上调用调用代码,而不要将它隐藏在实现F.e中。如果调用代码已经运行异步,没有理由产生另一个线程。 This article更详细地描述了这一点。

5

看来你是aysnc-await的新手。真正帮助我理解什么是异步等待的是Eric Lippert在this interview.中给出的餐厅类比在中间的某处寻找异步等待。

在这里他描述了如果一个厨师必须等待某件事情,而不是无所事事,他会开始环顾四周,看看他是否可以在此期间做其他事情。

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

通常在阅读你的大名单时,你的线程会非常忙,而不是闲着等。不确定订购另一个线程来完成这些工作会改善阅读您的列表所需的时间。考虑测量两种方法。

One reason to use async-await, even if it would lengthen the time needed to read the big list, would be to keep the caller (user interface?) responsive.

为了让你的函数异步,你应该做到以下几点:

  • 声明函数异步
  • 代替TResult回报Tast<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响应)做的,如果你是快不这样做,或至少测量。

,帮助我理解异步等待其他文章均 - Async await,由曾经如此有用斯蒂芬·克利里, - 还有一点点更先进:Async-Wait best practices

相关问题