5

控制檯應用程序利用的的情況下異步/等待結構,我想知道這是否是可能的「延續」並行多線程上運行不同的CPU。任務繼續並行執行與異步/等待

我認爲是這種情況,因爲continuations發佈在線程池的默認任務計劃程序(控制檯應用程序中沒有SynchronizationContext)上。

我知道async/await構造不會構造任何附加線程。仍然應該有至少一個線程池構成的每個CPU構造的線程,因此如果在線程池中發佈延續,它可以在不同的CPU上平行安排任務延續......這就是我的想法,但由於某種原因,我昨天對此感到非常困惑,我不太確定了。

下面是一些簡單的代碼:

public class AsyncTest 
{ 
    int i; 

    public async Task DoOpAsync() 
    { 
    await SomeOperationAsync(); 

    // Does the following code continuation can run 
    // in parrallel ? 
    i++;  

    // some other continuation code .... 
    } 

    public void Start() 
    { 
    for (int i=0; i<1000; i++) 
    { var _ = DoOpAsync(); } // dummy variable to bypass warning 
    } 
} 

SomeOperationAsync本身並不創造任何線程,並假設爲例子的目的,它只是將一些請求異步地依賴於I/O完成因此不會阻塞任何線程。

現在,如果我打電話開始將發出1000個異步操作的方法,可以在不同的CPU線程上並行運行異步方法的延續代碼(在await之後)嗎?即在這種情況下是否需要處理線程同步並同步對字段「i」的訪問?

+0

你想讓它們平行運行嗎?如果你這樣做,很容易就可以同步所有的調用,只需'等待'Start'中的DoOpAsync'。 – Servy

回答

4

是的,你應該把線程同步邏輯放在i++左右,因爲多個線程可能會在await之後同時執行代碼。

作爲for循環的結果,將創建任務數量。這些任務將在不同的線程池線程上執行。一旦完成這些任務,繼續執行,即等待之後的代碼將在不同的線程池線程上再次執行。這使得多個線程可能同時在i ++上執行操作。

+0

感謝您的回答Haris! – darkey

2

您的理解是正確的:在控制檯應用程序中,默認情況下,由於缺省SynchronizationContext,繼續將安排到線程池。

每個async方法確實同步啓動,因此您的for循環將在同一個線程上執行DoOpAsync的開始。假設SomeOperationAsync返回一個不完整的Task,將在線程池上安排延續。

因此,每個調用DoOpAsync可能會並行繼續。

+0

感謝Stephen澄清:) – darkey