2014-11-06 33 views
4

我是新来的异步/等待,我想确保这样做的方式是正确的:await/async的这种用法是否正确?

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

是采用异步的这种方式/等待正确的还是我做错了什么?

+0

为什么事件,直到你需要它启动了吗? – 2014-11-06 15:27:04

+3

此代码不会编译,您在'ConsumeAsync'中缺少'async'关键字 – 2014-11-06 15:27:31

+0

这是桌面还是Web应用程序? – dcastro 2014-11-06 15:28:24

回答

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); 
    
2

从API设计师观点,我会考虑拆分方法getResponseFromFarawaySlowServerAndDoSomethingWithIt到:
getResponseFromFarawaySlowServerdoSomething()
然后你可以用异步包装包裹只有长时间运行的方法

使用将随后:

var response = await getResponseFromFarawaySlowServerAsync(); 
doSomething(response); 

闻起来有点另一件事:getResponseFromFarawaySlowServer本身不是异步。如果可能,应该在该方法内部等待http调用或web服务调用本身。目前,你正在创建新的线程,只是等待。这是多余的,如果你期待已久的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; 
}