73

スレッド作成に関しては 、TPL & async/の違いを理解しようとしています。await

TPL ( )は、スレッド プール内のスレッドの作業をキューに入れるという点で、 とTaskFactory.StartNew同様に機能すると思います。ThreadPool.QueueUserWorkItemもちろん、これを使用しない限りTaskCreationOptions.LongRunning、新しいスレッドを作成します。

私はasync/awaitと同様に機能すると思ったので、本質的に:

TPL:

Factory.StartNew( () => DoSomeAsyncWork() )
.ContinueWith( 
    (antecedent) => {
        DoSomeWorkAfter(); 
    },TaskScheduler.FromCurrentSynchronizationContext());

Async/ Await:

await DoSomeAsyncWork();  
DoSomeWorkAfter();

同一になります。私が読んだことから、async/ await「時々」だけ新しいスレッドが作成されるようです。では、いつ新しいスレッドを作成し、いつ新しいスレッドを作成しないのでしょうか? IO 完了ポートを扱っていた場合、新しいスレッドを作成する必要がないことがわかりますが、それ以外の場合は作成する必要があると思います。いつもの私の理解FromCurrentSynchronizationContextも少し曖昧だったと思います。本質的にはUIスレッドだといつも思っていました。

4

2 に答える 2

86

TPL (TaskFactory.Startnew) は、スレッド プール内のスレッドの作業をキューに入れるという点で、ThreadPool.QueueUserWorkItem と同様に機能すると思います。

かなり

私が読んだことから、 async/await は「時々」のみ新しいスレッドを作成するようです。

実際、決してそうではありません。マルチスレッドが必要な場合は、自分で実装する必要があります。Task.Runの省略形である新しいメソッドがありTask.Factory.StartNew、おそらくスレッド プールでタスクを開始する最も一般的な方法です。

IO 完了ポートを扱っていた場合、新しいスレッドを作成する必要がないことがわかりますが、それ以外の場合は作成する必要があると思います。

ビンゴ。そのため、 のようなメソッドStream.ReadAsyncは実際にTaskIOCP の周りにラッパーを作成します (IOCPStreamがある場合)。

非 I/O、非 CPU の「タスク」を作成することもできます。簡単な例はTask.Delayで、一定時間後に完了するタスクを返します。

async/の優れた点awaitは、いくつかの作業をスレッド プールにキューイングし (例: Task.Run)、I/O バウンド操作を実行し (例: Stream.ReadAsync)、その他の操作を実行できることです (例: Task.Delay)。すべてのタスク!それらは待機することも、 のように組み合わせて使用​​することもできますTask.WhenAll

返されるメソッドはすべてed にすることがTaskできますawait- メソッドである必要はありませんasync。そのTask.Delayため、I/O バウンド操作TaskCompletionSourceはタスクの作成と完了にのみ使用されます。スレッド プールで実行される唯一のことは、イベント発生時の実際のタスク完了 (タイムアウト、I/O 完了など) です。

FromCurrentSynchronizationContext の理解も常に少し曖昧だったと思います。本質的にはUIスレッドだといつも思っていました。

に記事を書きましたSynchronizationContext。ほとんどの場合SynchronizationContext.Current:

  • 現在のスレッドが UI スレッドの場合、UI コンテキストです。
  • 現在のスレッドが ASP.NET 要求を処理している場合、ASP.NET 要求コンテキストです。
  • それ以外の場合は、スレッド プール コンテキストです。

どのスレッドも独自の を設定できるSynchronizationContextため、上記の規則には例外があります。

null でない場合、デフォルトのTaskawaiter はasync現在のメソッドの残りをスケジュールすることに注意してください。それ以外の場合は、現在の状態になります。これは今日ではそれほど重要ではありませんが、近い将来、重要な違いになるでしょう。SynchronizationContext TaskScheduler

私は自分のasync/awaitイントロを自分のブログに書きました。Stephen Toub は最近、優れたasync/ awaitFAQを投稿しました。

「同時実行」と「マルチスレッド」については、この関連する SO の質問を参照してください。asyncマルチスレッド化されている場合とされていない場合があります。await Task.WhenAll並列処理を使用または実行するのは簡単await Task.WhenAnyで、明示的にスレッド プール (Task.Runまたは などConfigureAwait(false)) を使用しない限り、複数の同時操作を同時に進行させることができます (たとえば、複数の I/O または のような他のタイプDelay) -それらに必要なスレッドはありません。私はこの種のシナリオに対して「シングルスレッド同時実行」という用語を使用していますが、ASP.NET ホストでは、実際には「ゼロスレッド同時実行」になる可能性があります。これはかなり甘いです。

于 2012-04-23T18:56:51.603 に答える
9

async / await は基本的にContinueWithメソッドを簡素化します (継続渡しスタイルの継続)

同時実行性は導入されません - 自分で行う必要があります (またはフレームワーク メソッドの Async バージョンを使用します)。

したがって、C# 5 バージョンは次のようになります。

await Task.Run( () => DoSomeAsyncWork() );
DoSomeWorkAfter();
于 2012-04-23T17:27:39.360 に答える