我是async/await的新手,我想确保这种方式是正确的:
public async Task DoHeavyWorkAsync()
{
await Task.Run(() => {
getResponseFromFarawaySlowServerAndDoSomethingWithIt();
});
}
public async void ConsumeAsync()
{
Task longRunningTask = DoHeavyWorkAsync();
// do a lot of other stuffs here that does not depend on DoHeavyWorkAsync()
await longRunningTask;
}
这种使用 async/await 的方式是正确的还是我做错了什么?
您可以做几件事:
-
在
DoHeavyWorkAsync
中,你其实不需要用await Task.Run
生成状态机,你可以简单地return Task.Run
:public Task DoHeavyWorkAsync() { return Task.Run(() => getResponseFromFarawaySlowServerAndDoSomethingWithIt()); }
-
async void
仅用于异步事件处理程序。如果异步方法void
返回,则应改为返回Task
:public async Task ConsumeAsync()
-
如果
DoHeavyWorkAsync
是基于 IO 的操作,则无需将其包装在Task.Run
中,因为它本质上是异步的。只需使用await
就可以了。更重要的是,您不应该通过同步进行异步。相反,您应该使同步方法的调用方显式使用Task.Run
,如果需要的话:public void DoHeavyWork() { getResponseFromFarawaySlowServerAndDoSomethingWithIt(); }
然后将其显式包装在调用方法中:
Task.Run(DoHeavyWork);
从 API 设计者的角度来看,我会考虑将方法拆分getResponseFromFarawaySlowServerAndDoSomethingWithIt
为:
getResponseFromFarawaySlowServer
和doSomething()
.
然后,您可以使用异步包装器仅包装长时间运行的方法
然后用法将:
var response = await getResponseFromFarawaySlowServerAsync();
doSomething(response);
另一件闻起来有点闻的东西:getResponseFromFarawaySlowServer
本身不是异步的。 如果可能的话,应该在该方法中等待 HTTP 调用或 WebService 调用本身。目前您正在创建新线程 thad 什么都不做,只是等待。如果您等待 http 调用,这是多余的
所以相反
string getResponseFromFarawaySlowServer(){
string response = new WebClient().DownloadString(uri);
...
return response
}
async Task<string> getResponseFromFarawaySlowServerAsync(){ Task.StartNew..
您将直接:
async Task<string> getResponseFromFarawaySlowServerAsync(){
string response = await new WebClient().DownloadStringAsync(uri);
...
return response;
}