According to MSDN、async
とawait
せずに待っています:理解非同期は/新しいスレッドを作成していないスレッド
async
とawait
キーワードは、追加のスレッドが作成されることはありません。
これを念頭に置いて、いくつかの簡単なプログラムの制御フローを理解するのが難しいです。私の完全な例は以下の通りです。 NuGetからインストールできるDataflow libraryが必要です。
using System;
using System.Threading.Tasks.Dataflow;
namespace TaskSandbox
{
class Program
{
static void Main(string[] args)
{
BufferBlock<int> bufferBlock = new BufferBlock<int>();
Consume(bufferBlock);
Produce(bufferBlock);
Console.ReadLine();
}
static bool touched;
static void Produce(ITargetBlock<int> target)
{
for (int i = 0; i < 5; i++)
{
Console.Error.WriteLine("Producing " + i);
target.Post(i);
Console.Error.WriteLine("Performing intensive computation");
touched = false;
for (int j = 0; j < 100000000; j++)
;
Console.Error.WriteLine("Finished intensive computation. Touched: " + touched);
}
target.Complete();
}
static async void Consume(ISourceBlock<int> source)
{
while (await source.OutputAvailableAsync())
{
touched = true;
int received = source.Receive();
Console.Error.WriteLine("Received " + received);
}
}
}
}
出力:
これはfor
ループの実行中に
OutputAvailableAsync
タスクが完了するよう
Consume
は、制御を与えていることを示していると思われる
Producing 0
Performing intensive computation
Received 0
Finished intensive computation. Touched: True
Producing 1
Performing intensive computation
Received 1
Finished intensive computation. Touched: True
Producing 2
Performing intensive computation
Received 2
Finished intensive computation. Touched: False
Producing 3
Performing intensive computation
Received 3
Finished intensive computation. Touched: False
Producing 4
Performing intensive computation
Received 4
Finished intensive computation. Touched: True
:
for (int j = 0; j < 100000000; j++)
;
これはで驚くだろうスレッドモデル。しかし、追加のスレッドが含まれていない場合、どのようにfor
ループの途中でProduce
の制御を行うことができますか?
@ I4V:この質問に対する答えは、「すべてのブロック操作が明示的に非同期/待機モデルを使用して制御を行う必要がある」と述べています。しかし、私の質問では、コントロールは明示的に制御を行う「生産」なしで、「生産」から「消費」に移行します。それは私が混乱している部分です。 –
@Matthewこれはコンソールアプリケーションであるため、 'SynchronizationContext'はありません。つまり、' await'呼び出しからのコールバックはすべてスレッドプールである 'SynchronizationContext.Default'に移動するので、実際には2つのスレッドが実行されていますこのプログラムの実行中に時々。追加のスレッドが作成されないようにするには、独自のカスタム同期コンテキストを作成して設定する必要があります。もしあなたがそうしたなら、あなたは生産中にコントロールを得ていないので、すべての生産が具体的に行われるまで、 'Recieved'コールが呼び出されないことが分かります。 – Servy
@Servy:複数のスレッドが関与している場合、MSDNは「特に、競合状態を防ぐ必要がないため、このアプローチはIOバインド操作ではBackgroundWorkerよりも優れています」と主張しています。簡単な競合条件を追加するために私の例を編集しました。 –