2016-02-18 17 views
6

私は、次のコード作成:asyncとawaitはシングルスレッドです本当ですか?

using System; 
using System.Threading.Tasks; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main() 
     { 
     Console.WriteLine("M Start"); 
     MyMethodAsync(); 
     Console.WriteLine("M end"); 
     Console.Read(); 
     } 

    static async Task MyMethodAsync() 
    { 
     await Task.Yield(); 
     Task<int> longRunningTask = LongRunningOperationAsync(); 
     Console.WriteLine("M3"); 
     //and now we call await on the task 
     int result = await longRunningTask; 
     //use the result 
     Console.WriteLine(result); 
    } 

     static async Task<int> LongRunningOperationAsync() 
     { 
     await Task.Delay(1000); 
     return 1; 
     } 
    } 
} 

出力:その後、 enter image description here そして、この:罰金ですが、私はスレッド・プロファイラーでその番組を見たときに、この

M Start 
M end 
M3 
1 

enter image description here をと次に: enter image description here

私はスレッドを生成が、MSDNから言うように:非同期と待つと非同期プログラミングから

:スレッド

非同期およびキーワードを待つには、追加のスレッドが が作成されることはありません。非同期メソッドは、非同期 メソッドが独自のスレッドで実行されないため、マルチスレッドを必要としません。このメソッドは、現在の 同期コンテキストで実行され、 メソッドがアクティブな場合にのみ、スレッドで時間を使用します。 Task.Runを使用してCPUバインドされた作業を バックグラウンドスレッドに移動できますが、バックグラウンドスレッドは結果が利用可能になるのを待っているプロセス では役に立ちません。

何か不明か何かを理解していませんか?おかげさまで

+2

スレッドプールの既存のスレッドを使用します。作成しないでください –

+1

Visual Studioでは本当に気の利いたウィンドウのようです。トピック以外の質問に申し訳ありませんが、どのバージョンでサポートされていますか? –

+0

あなたの出力を 'Thread.CurrentThread.ManagedThreadId'で装飾すると、3つのスレッドが使用されていることが分かります。 –

答えて

7

私のブログにhow async and await work with threads and contextsを説明します。要約すると、awaitが非同期操作が完了するのを待つ必要があるとき、現在のasyncメソッドを「一時停止」し、(デフォルトでは)「コンテキスト」を取得します。

非同期操作が完了すると、その "コンテキスト"がasyncメソッドを再開するために使用されます。この「コンテキスト」は、nullでない限りSynchronizationContext.Currentであり、その場合はTaskScheduler.Currentです。あなたのケースでは、コンテキストはスレッドプールコンテキストになりますので、asyncメソッドの残りの部分はスレッドプールに送られます。 UIスレッドから同じコードを実行すると、コンテキストはUIコンテキストになり、すべてのasyncメソッドがUIスレッドで再開します。

2

asyncキーワードとawaitキーワードでは、追加のスレッドが作成されません。

はい。これは、UIスレッドまたは現在の同期コンテキストでは実行されないように、CPUバインドまたはI/Oバウンド作業をプロセスのスレッドプールから他のスレッドに移動し、MSDN記述の意味での新しいスレッドを作成しません。

+0

しかし、すべてのスレッドが消費されている場合は、待機します。右? –

+1

これは間違っています。タスクは、現在の同期コンテキストで実行されます。別のスレッドは、スレッドプールベースの同期コンテキストを使用する場合にのみ使用されます。そうでない場合は、すべてがメインスレッド上でキューで処理されます。 "continuation-passing style"については、非同期での動作方法をご覧ください。 –

関連する問題