26

よくわかりません。 1人または多数Taskシングルスレッドで並列に実行する?私の理解並列性明らかに間違っています。

MSDNのビット私は頭を包むことはできません:

asyncキーワードとawaitキーワードによって追加のスレッドが発生することはありません。   作成した。非同期メソッドはマルチスレッドを必要としません   メソッドはそれ自身のスレッドでは実行されません。メソッドは現在のメソッドで実行されます。   同期コンテキストを使用して、スレッドの時間を   メソッドはアクティブです。

..そして:

タスクの開始から待機までの間に、他のタスクを開始できます。   追加のタスクは暗黙的に並列実行されますが、追加のタスクはありません。   スレッドが作成されます。

1 답변


24

それらは並行して走るのではなく、交代します。実行中のタスクの進行状況がブロックされると、その状態が保存され、準備が整ったタスクに制御が移ります。これは協調的マルチタスクであり、真の並列処理ではありません。

スレッドはサンプル原則に基づいて動作します。しかし、強調したいことがいくつかあります。

まず、という理由だけでasync/awaitOSのスレッドではありません:

  • タスクは異なるスレッドIDを見ない
  • タスクが譲渡されたときにスレッドローカルストレージは自動的にコンテキストスイッチされません。

第二に、行動の違い:

  • async/await協調的マルチタスクを使用し、Win32スレッドは横取りを使用します。そのため、すべてのブロッキング操作で明示的にasync/awaitモデル。そのため、yieldされていない関数へのブロッキング呼び出しを行うことで、スレッド全体とそのすべてのタスクをブロッキングすることになります。
  • タスクはマルチプロセッシングシステム上で並行して実行されることはありません。再入可能性が制御されているので、これによってデータ構造の一貫性を非常に簡単に保つことができます。

Stephenがコメントで指摘しているように、あなたはできるマルチスレッド同期コンテキストを使用すると、(すべての複雑さと潜在的な競合状態と共に)複数のOSスレッドで同時に実行されます。しかし、MSDNの引用はシングルスレッドのコンテキストに関するものでした。

最後に、この同じ設計パラダイムが使用されている他の場所では、以下のための優れた実践について多くを学ぶことができます。async/awaitこれらを学ぶことによって:

  • Win32繊維(スレッドと同じ呼び出しスタイルを使用しますが、協調的です)
  • Win32重複したI / O操作、Linuxに行きます
  • コルーチン


  • 「ブロック」 asyncの目的はブロックを回避することであるため、ここで使用するのはわかりにくい用語です。 - Cory Nelson
  • +1。そのことに注意してくださいasyncメソッドはブロックされたときの状態と歩留まりを保存しますawait。ブロッキングコードを実行している場合(Thread.Sleep)、それからその状態と収量を保存しませんでした。 - Stephen Cleary
  • @Cory:個々のタスクがブロックされ、スレッドが実行されない(Stephenが言っているように、これはあなたがすべてのものに対してコルーチンを使用している場合にのみ当てはまる)。 - Ben Voigt
  • 私はそれが明確にされるべきだと思います、なぜMSはこれをWROTEにします。多くの人が、「非同期」と考えています。メソッドを非同期に(別のスレッドで)実行するようにします。いいえ、違います。そしてまたawait SomeMethodAsync()AWAITのため、新しいスレッドを作成しません。 SomeMethodAsyncが新しいスレッドを作成すると、新しいスレッドが作成されます(必ずしもそうではありません)。 - igrimpe
  • @ BenVoigt:あなたの最新の回答の多くは、asyncシングルスレッド内で実行されるメソッドSynchronizationContext(UIコンテキストなど)コンソールアプリケーションまたはバックグラウンドスレッドから実行されている場合は、Tasksはスレッドプールで実行され、意志以下の場合を除いて、並列に(マルチスレッドで)実行します。awaitそれぞれ個別に。 - Stephen Cleary

リンクされた質問


関連する質問

最近の質問