2014-11-06 29 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; 
}