2014-08-29 79 views
0

假設下面的方法被定義:我應該使用常規任務還是繼續任務?

Task<TResult> DoStuffAsync() 
{ 
    // ... 
} 

考慮下面的代碼(片斷1):

void MyFunction() 
{ 
    Task<TResult> task = DoStuffAsync(); 
    task.ContinueWith(async() => { 
     TResult result = await task; 
     // do stuff with result 
    }); 
    // poll `task` status... 
} 

相比於以下代碼(代碼段2):

void MyFunction() 
{ 
    Task<TResult> task = DoStuffAsync(); 
    Task.Run(async() => { 
     TResult result = await task; 
     // do stuff with result 
    }); 
    // poll `task` status... 
} 

(注意我怎麼不關心lambda函數的狀態(fire-and-forget)。但我關心它是否是r 。aises任何例外)

兩個選項之間的第一差似乎很清楚:在(片斷1)在lambda代碼將僅開始執行DoStuffAsync()完成之後,而在(片斷2)在所述代碼lambda將嘗試立即開始執行,並在DoStuffAsync()完成時繼續。

但是,除了這種差異,您應該何時使用ContinueWith以及何時應該使用Task.Run?如果在DoStuffAsync()或lambda函數中引發異常,會發生什麼情況?它會被吞噬還是每個潛在的異常都會被保證提升到可以處理的地方?

+0

首先,您不應該在啓動它後查詢任務的狀態。這是一個很大的紅旗。 – Servy 2014-08-29 16:39:17

+1

你爲什麼需要?只是做結果=等待DoStuffAsync();似乎是一個更好的選擇。 – ths 2014-08-29 16:40:14

回答

2

在您的第一個案例中,不需要將lambda設置爲async。沒有必要await的任務。您可以使用Result,因爲您知道該任務在該時間點已經完成。

對於第二個示例,您正在調度線程池線程以執行狀態機的創建,該狀態機僅在任務完成時安排一些代碼運行。這根本不需要。 Task.Run在這裏沒有添加任何內容。

最有可能的方法本身應該是一個async方法:

private async Task MyFunction() { 
    var result = await DoStuffAsync(); 
    // do stuff with result 
} 

所有這一切說,只有在您的解決方案有很多多餘的工作,既會傳播異常從基礎工作的任務是每個操作都會計算(儘管在第一個示例中不會將該任務存儲在任何地方,因此您無法檢查該任務以查看是否出現故障)。

相關問題