2013-01-17 207 views
8

我開始學習C#5和.Net 4.5中的異步編程,但有些東西我不明白。異步編程並等待循環

private static int count; 

public static void Main() 
{ 
    LoopTest(); 

    Console.ReadKey(false); 
} 

static async void LoopTest() 
{ 
    count = 0; 

    for (var index = 0; index < 10; ++index) 
    { 
     Console.WriteLine("({0}) In Loop before await, Index {1}, Thread: {2}", count++, index, Thread.CurrentThread.ManagedThreadId); 
     await Task.Factory.StartNew(() => Thread.Sleep(10)); 
    } 
} 

結果是:

(0) In Loop before await, Index 0, Thread: 9 
(1) In Loop before await, Index 1, Thread: 10  
(2) In Loop before await, Index 2, Thread: 11 
(3) In Loop before await, Index 3, Thread: 10 
(4) In Loop before await, Index 4, Thread: 11 
(5) In Loop before await, Index 5, Thread: 10 
(6) In Loop before await, Index 6, Thread: 12 
(7) In Loop before await, Index 7, Thread: 11 
(8) In Loop before await, Index 8, Thread: 10 
(9) In Loop before await, Index 9, Thread: 12 

那麼,有沒有不同的線程訪問相同的循環?索引變量是否存在Race-Condition?

+0

請替換await Task.Factory.StartNew(()=> Thread.Sleep(10));等待Task.Delay(10)。你應該放開你的線程10毫秒,而不是堅持下去。 –

+0

@publicENEMy所以'Task.Delay';) –

+2

@ToniPetrina Thread.Sleep用於保存線程以模擬10 ms線程的使用情況。 –

回答

13

不,沒有競賽條件。你開始一個新的任務,它將在後臺運行,但是你的代碼在任務完成之前不會繼續,所以你可以確定你的代碼只能在一個線程中一次執行。

但是,因爲這是一個控制檯應用程序,目前沒有SyncronizationContext。 (而不是WinForm,WPF,ASP,Silverlight等應用程序)。這意味着任何await調用的延續都將在線程池中運行,而不是在調用線程中運行。所以是的,你在循環的每次迭代中都運行在一個線程池線程中,並且它可能每次都是一個不同的線程,但是你可以確定,除了你在新任務中放置的任何東西,你將會「完成「在任何給定的線程上運行,然後開始下一個線程,這確保了在任何給定時間只有一個線程運行代碼(這意味着沒有競爭條件)。

+0

感謝您的回答!我明白 :) – m1o2

4

你正在做什麼是不是真的asycnhronous

await Task.Factory.StartNew(() => Thread.Sleep(10)); 

這將創建一個任務,然後等待該任務完成。你也可以在這裏調用Thread.Sleep(10)。

一個更合適的方式來做到這將是:

Task myTask = Task.Factory.StartNew(() => Thread.Sleep(10)); 
... do stuff here ... 
await myTask; // Now wait for the task to complete 

如果你想要做一個循環多項任務,你應該看看Parallel.Foreach()方法。

+0

感謝您的回答!但我有幾個問題。 如果我在當前線程上創建任務,那麼誰在創建線程的其餘部分?或爲什麼ManagedThreadId不斷變化? – m1o2

+7

這個例子只是一個玩具的例子,他正在試驗並試圖解釋結果。這並不能解釋這些結果,並且試圖說這個測試是錯誤的,當它沒有嘗試完成時就沒有解釋「await」的工作原理。 – Servy

+0

對不起,我從答案中刪除了我錯誤的「關於當前主題」的短語。這些任務在線程池中運行,並不一定會像創建任務一樣創建多個線程。它會嘗試爲您管理資源,這是在線程上使用它的優勢之一。 – Pete