2015-11-20 53 views
3

我對c#async/await機制有一些誤解。 有什麼時候多重等待有意義?

private async void Init() 
{ 
    await Task.Run(() => Do1()); 
    await Task.Run(() => Do2()); 
} 

private async void Init() 
{ 
    await Task.Run(() => 
    { 
     Do1(); 
     Do2(); 
    }); 
} 

我看到的唯一的區別之間的本質區別:第一個樣品在D01和D02會在不同的線程來運行,而第二個樣品中 - 在同一線。但是,再次,它的真正好處是什麼,當我更喜歡第一種方法而不是第二種方法時,反之亦然?


編輯:第二種情況

是什麼

private async void Init() 
{ 
    await Task.Run(() => Do1()); 
    Do3(); 
} 

private async void Init() 
{ 
    await Task.Run(() => 
    { 
     Do1(); 
     Do3(); 
    }); 
} 
+0

在你的具體情況下,第二種方法更好。因爲Do1之後的任何方式,Do2將被執行,所以結果沒有區別。 task.run在第一種方法中增加了一些開銷。還要注意的是,在兩種情況下,Do1都會先運行,然後在第一種情況下Do2啓動 –

+0

@ M.kazemAkhgary,當任務正在啓動時,它們是否會一個接一個地運行,然後我們馬上等待?即,如果它們被分配給變量並在等待第一個變量之前啓動它們,它們是否會同時運行? – Dhunt

+0

是的。如果您將它們存儲在變量中,然後等待它們單獨運行,但現在因爲在創建任務之後等待它們開始一個接一個@Dhunt –

回答

3

的區別是:

第一個例子:

  • 您排隊Do1一個線程池線程並異步等待它完成,然後與Do2完全相同。這些可能運行在不同的線程上。
  • 排隊Do1Do2在同一個線程池線程上一個接一個地同步執行。

第二個例子:

  • 隊列Do1上線程池和異步等待它完成,然後調用Do3同步。
  • 這與第一個例子的第二部分完全相同。

請注意,當你await,你異步等待操作完成,因此,除非方法完成,它不會執行下一行代碼。

我假設你問自己,如果一個人比另一個人更好,並且在大多數情況下,這取決於。如果您正在控制檯應用程序中運行,並且您將異步等待Do1完成,則將這兩種方法都傳遞給相同的Task.Run調用。如果您打算在同步很重要的地方(例如GUI應用程序)執行此操作,則需要在UI線程上調用需要與UI控件交互的任何操作。

另一種更常見的選擇是當您有兩個彼此獨立的操作,並且您希望一起啓動它們並等待兩者完成時。在這裏,你會使用Task.WhenAll

var firstDo = Task.Run(() => Do1()); 
var secondDo = Task.Run(() => Do2()); 
await Task.WhenAll(firstDo, secondDo); 

旁註:

不要在異步方法使用async void沒有返回值,這就是async Task是。前者只是爲了與事件處理程序兼容,我假設事實並非如此。

0
  • 如果Do1()Do2()是相互獨立的,你應該運行它們之間的區別分別。如果它們是長時間運行/阻塞進程,則這更爲重要
  • 另一方面,如果它們是相關的,並且第一個執行另一個所需的某些操作,那麼最好在一個線程中運行它們以減少線程開銷。畢竟,你事先知道他們需要運行順序
+0

在這兩種情況下,它們都運行另一個。我看到的唯一區別是:在第一種情況下,它們將在各自的線程中運行。但不是同時!第二項任務的線程將在第一項任務完成後啓動。所以除了一些性能開銷之外,我沒有看到這些情況之間的任何本質區別。 – Sergey

相關問題