这种await / async的用法是否正确?

时间:2014-11-06 15:26:09

标签: c# .net asynchronous async-await task-parallel-library

我是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的方式是正确的还是我做错了什么?

2 个答案:

答案 0 :(得分:7)

你可以做几件事:

  1. DoHeavyWorkAsync中,您真的不需要使用await Task.Run生成状态机,您只需return Task.Run

    public Task DoHeavyWorkAsync() 
    {
       return Task.Run(() => getResponseFromFarawaySlowServerAndDoSomethingWithIt());
    }
    
  2. async void仅适用于异步事件处理程序。如果您的异步方法返回void,则应返回Task代替:

    public async Task ConsumeAsync()
    
  3. 如果DoHeavyWorkAsync是基于IO的操作,则无需将其包含在Task.Run内,因为它本身是异步的。只需使用await即可。更重要的是,你不应该async over sync。相反,如果需要,您应该使同步方法的调用者明确使用Task.Run

    public void DoHeavyWork()
    {
        getResponseFromFarawaySlowServerAndDoSomethingWithIt();  
    }
    

    然后将其显式包装在调用方法中:

    Task.Run(DoHeavyWork);
    

答案 1 :(得分:2)

从API设计师的角度来看,我会考虑将拆分方法 getResponseFromFarawaySlowServerAndDoSomethingWithIt改为:
 getResponseFromFarawaySlowServerdoSomething()
然后,您只能使用异步包装器

包装长时间运行的方法 然后

使用:

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;
}