7

async / awaitコンストラクトを使用するコンソールアプリケーションのコンテキストで、異なるCPU上の複数のスレッドで「継続」を並行して実行できるかどうかを知りたいと思います。

継続はデフォルトのタスクスケジューラ(コンソールアプリにはSynchronizationContextなし)に投稿されるため、これが当てはまると思います。これはスレッドプールです。

async/awaitコンストラクトが追加のスレッドをコンストラクトしないことを私は知っています。それでも、スレッドプールによってCPUごとに少なくとも1つのスレッドが構築される必要があるため、継続がスレッドプールに投稿されると、異なる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回の非同期操作を発行するStartメソッドを呼び出すと、(await後の)asyncメソッドの継続コードを異なるCPUスレッドで並行して実行することは可能ですか?つまり、この場合、スレッドの同期を処理し、フィールド「i」へのアクセスを同期する必要がありますか?

4

2 に答える 2

6

はい、複数のスレッドが同時にi++コードを実行する可能性があるため、スレッド同期ロジックを配置する必要があります。await

forループの結果として、いくつかのタスクが作成されます。これらのタスクは、さまざまなスレッドプールスレッドで実行されます。これらのタスクが完了すると、継続、つまり待機後のコードが、別のスレッドプールスレッドで再度実行されます。これにより、複数のスレッドが同時にi++を実行する可能性があります

于 2013-01-22T16:55:11.690 に答える
6

あなたの理解は正しいです:コンソールアプリケーションでは、デフォルトでは、デフォルトのために継続がスレッドプールにスケジュールされますSynchronizationContext

asyncメソッドは同期的に開始されるため、forループはDoOpAsync同じスレッドで開始を実行します。SomeOperationAsyncが不完全なものを返すと仮定するとTask、継続はスレッドプールでスケジュールされます。

したがって、の各呼び出しはDoOpAsync並行して続行できます。

于 2013-01-22T17:17:20.450 に答える