2016-03-08 243 views
1

方法1:這兩種任務方法的行爲有什麼不同?

private static async Task FirstDelayAsync() 
{ 
    await Task.Delay(1000); 
} 

方法2:

private static Task SecondDelayAsync() 
{ 
    return Task.Delay(1000); 
} 

請幫我找的區別:

await FirstDelayAsync(); 
await SecondDelayAsync(); 

感謝。

+5

一個叫做'First',另一個叫'Second'。一個是「異步」,另一個不是。這不是http://puzzling.stackexchange.com。你真的想知道什麼?你的問題[如何異步調用同步方法](http://stackoverflow.com/questions/18830397/awaiting-a-non-async-method)? – CodeCaster

+1

@CodeCaster:這是一個合理的問題。即使兩者之間沒有功能上的差異(事實並非如此),OP的要求也是合理的。但是,這可能是一個重複的問題。 – Douglas

+0

爲了DRY的利益標記爲重複。儘管它的標題,鏈接的問題和它接受的答案主要討論'Task.Delay'的情況,而不是'Task.Run'。 – Douglas

回答

4

這兩者非常相似。遇到async方法時,C#編譯器將生成一個狀態機,以便返回的Task表示方法的完成。由於您的方法所做的唯一工作是等待另一個異步操作,因此這在功能上幾乎等同於直接從內部異步操作返回Task

然而,關於如何拋出同步部分的異常有一個細微的區別。在async方法中執行的任何邏輯包括該方法開始處的同步部分(在第一個await語句之前)將被編譯爲異步操作的一部分。這意味着,前提例外將不再同步發送,而是通過異步返回Task

private static async Task FirstDelayAsync() 
{ 
    if (StateNotValid) 
     throw new NotSupportedException(); 

    await Task.Delay(1000); 
} 

private static Task SecondDelayAsync() 
{ 
    if (StateNotValid) 
     throw new NotSupportedException(); 

    return Task.Delay(1000); 
} 

測試了上面的代碼:

var t1 = FirstDelayAsync(); 
await t1;      // exception thrown here 

var t2 = SecondDelayAsync(); // exception thrown here 
await t2; 

,如果你等待這不會有所作爲您在您稱之爲同一行的異步操作。但是,如果你推遲等待,這會有所作爲;例如,如果您同時推出幾個異步操作,然後等待他們使用Task.WhenAll在一起:

var tasks = Enumerable 
    .Range(0, 10) 
    .Select(i => ProcessAsync(i)) 
    .ToArray(); 

await Task.WhenAll(tasks); 

在上面的代碼中,從ProcessAsync調用拋出同步異常會阻止甚至正在啓動的後續異步操作,因爲異常立即停止枚舉。這通常適用於應該停止整個過程的失敗前提條件。

更新:另一個重要的不同之處在於使用await沒有ConfigureAwait(false)將會使你的代碼更容易死鎖。見this answer

0

功能上,這兩種方法沒有區別。他們的工作是一樣的。

asyncawait允許您創建複雜的異步方法,允許您編寫看起來像同步代碼但實際上是異步的代碼。

對於類似於你所擁有的簡單例子,第二種方法是首選,因爲第一種方法創建一個狀態機來處理異步邏輯。對於複雜的異步方法,這樣的狀態機肯定是需要的,但對於這種簡單的情況並不需要。

相關問題