2013-01-17 13 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 

だから、同じループへのアクセスが異なるスレッドがありますか?インデックス変数に競争条件がありますか?何をやっている

+0

Task.Factory.StartNew(()=> Thread.Sleep(10))を待ってください。 Task.Delay(10)を待ちます。あなたは10ミリ秒間あなたのスレッドを離れることになっています。 –

+0

@publicENEMYも同様に 'Task.Delay';) –

+2

@ ToniPetrina Thread.Sleepは、10msのスレッド使用量をシミュレートするためにスレッドを保持するために使用されます。 –

答えて

13

いいえ、競合状態はありません。バックグラウンドで実行される新しいタスクを開始しますが、そのタスクが終了するまでコードは続行されないため、コードはいつでも1つのスレッドでのみ実行されます。

ただし、これはコンソールアプリケーションであるため、現在はありませんSyncronizationContextです。これは、await呼び出しの続きがスレッドプールで実行され、呼び出し元のスレッドでは実行されないことを意味します(これは、winform、WPF、ASP、Silverlightなどのアプリケーションとは異なります)。だから、ループの各繰り返しでスレッドプールスレッドの1つで実行されているし、毎回別のスレッドプールスレッドを実行している可能性がありますが、新しいタスクの中に入れたものを除いて、次のスレッドで作業を開始する前に任意のスレッドで実行され、常に競合状態が発生していないことを意味するスレッドが1つしかないことを保証します。

+0

あなたの答えをありがとう!わかりました :) – m1o2

4

これは、タスクを作成し、そのタスクが完了するのを待って

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

本当にasycnhronousではありません。あなたはここでも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

この例は、彼が実験していて、結果を説明しようとしている単なるおもちゃの例です。これは結果を説明するものではなく、テストが間違っていると言うことを試みているのです。 – Servy

+0

申し訳ありませんが、私は間違って "現在のスレッドで"というフレーズを答えから削除しました。タスクはスレッドプール内で実行され、タスクを持つスレッドと同じ数のスレッドを作成する必要はありません。それはあなたのためにリソースを管理しようとしますが、これはスレッドを使ってそれを使う利点の一つです。 – Pete

関連する問題