web-dev-qa-db-ja.com

非同期デリゲートとスレッド/スレッドプール?

3つの並列タスクを実行する必要があり、各タスクの完了後に、結果を出力する同じ関数を呼び出す必要があります。

.netで、なぜ非同期呼び出し(delegate.BeginInvoke()&delegate.EndInvoke())とThreadクラスがあるのか​​わかりませんか?

どちらをいつ使うのか少し混乱していますか?この特定のケースでは、非同期呼び出しまたはスレッドクラスを何に使用する必要がありますか?

私はC#を使用しています。

33
claws

1。非同期デリゲート

非同期呼び出しは、バックグラウンドで処理する必要のある作業項目があり、終了時に気になる場合に使用されます

BackgroundWorkerとバックグラウンドスレッド

2。 BackgroundWorker

  • バックグラウンドで実行される単一のタスクがあり、UIと対話する必要がある場合は、BackgroundWorkerを使用します。そしてタスクがいつ終了するか気にしない場合に使用します。データのマーシャリングとUIスレッドへのメソッド呼び出しのタスクは、イベントベースのモデルを通じて自動的に処理されます。
  • BackgroundWorkerを回避する(1)アセンブリがまだSystem.Windows.Formアセンブリを参照していない場合、(2)スレッドがフォアグラウンドスレッドである必要がある場合、または(3)スレッドの優先順位を操作する必要があります。

3。 ThreadPool

  • 効率が必要な場合は、ThreadPoolスレッドを使用します。 ThreadPoolは、スレッドの作成、開始、および停止に関連するオーバーヘッドを回避するのに役立ちます。
  • ThreadPoolの使用は避けてください。(1)タスクがアプリケーションの存続期間中実行される場合、(2)スレッドがフォアグラウンドスレッドである必要がある場合、( 3)スレッドの優先順位を操作する必要がある、または(4)スレッドに固定ID(中止、一時停止、検出)を持たせる必要がある。

4。スレッドクラス

  • 長時間実行されるタスクや、前景スレッドと背景スレッドの選択、微調整など、正式なスレッドモデルによって提供される機能が必要な場合は、Threadクラスを使用します。スレッドの優先順位、スレッドの実行に対するきめ細かい制御など。
44
claws

.netで、なぜ非同期呼び出し(delegate.BeginInvoke()&delegate.EndInvoke())とThreadクラスがあるのか​​わかりませんか?

  • 非同期呼び出しは、バックグラウンドで処理する必要のある作業項目があり、それらが終了したときに気にする場合に使用されます。

  • スレッドプールは、バックグラウンドで処理する必要のある作業項目があり、それらがいつ終了するかを気にしない場合に使用します。

  • スレッドは、決して終わらないことをするためのものです。

例:

ディスクから大きなファイルを読み取っていて、GUIスレッドをブロックしたくない場合は、非同期呼び出しを使用します。

バックグラウンドで1つ以上のファイルを遅延書き込みしている場合は、スレッドプールを使用してください。

変更されたものを探すために数秒ごとにファイルシステムをポーリングしている場合は、スレッドを使用してください。

12
Jonathan Allen

非同期メソッドは、基本的に、作業が実際に処理されている方法を抽象化します。新しいプロセスに生成される場合もあれば、別のスレッドで実行される場合もあります...問題ではありません。

重要なのはあなたが言っていることです:

  1. 起動時にこのコードを実行します。
  2. 終了したら、このコードを実行します。

選択肢があれば、毎回独自のスレッドメカニズムを実装するのではなく、API非同期メソッドを使用します。フレームワーク開発者はあなたのために大変な仕事をしました、なぜ車輪を再発明するのですか?.

5
FlySwat

.netで、なぜ非同期呼び出し(delegate.BeginInvoke()&delegate.EndInvoke())とThreadクラスがあるのか​​わかりませんか?

一般に、非常によく設計されたシステムであっても、1つのことを行うには常に複数の方法があります。これは、一部の機能が低レベルの機能から構築された高レベルの機能であるためです。あなたのニーズに合ったハイレベルな施設があれば、それはあなたの幸運な日です。そうでない場合は、低レベルの機能を使用して自分で構築する必要があります。

ThreadクラスはWin32のBeginThreadを使用するため、使用する必要はありません。スレッドプールはThreadクラスを使用するため、使用する必要はありません。 BeginInvokeはスレッドプールを使用するため、使用する必要はありません。

3

非同期デリゲートは、スレッドプールのスレッドを使用して実行されます。これにより、手動でスレッドを作成して破棄するオーバーヘッドが削減されます。スレッドプールスレッドは、手動で作成したスレッドよりもオーバーヘッドが少なく、破棄する必要があります。

また、手動で作成されたスレッドでメソッドを実行すると、スレッドの割り込み、中止、状態の確認、優先度の設定など、より詳細な制御が可能になります。

メソッドを非同期ですばやく実行する場合は、非同期デリゲートが使用されます。

また、EndInvokeを使用すると、実行の結果を取得できるオブジェクトを返すことができます。 Thread.Joinは、機能的には同等ですが、何も返すことはできません。

1
bobbyalex

これは長い間忘れられていたスレッドですが、ここでまったく言及されていないのは、コンピューティングとI/Oバウンドの2種類の作業があるということです。

コンピューティングバウンド作業の場合、これは別のスレッドで実行されます(BackgroundWorkerまたはBegin/Endパターンを使用する場合、これはスレッドプールから取得されます。または、作成することにした場合はカスタムスレッドあなた自身のスレッド)。

一方、バインドされたI/OはI/Oポート(ハードウェアサポート)で実行され、スレッドを必要としません。ファイルアクセスとネットワークソケットは、I/Oバウンドタスクの2つの例です。

1
Jose

Delegate.BeginInvokeは、スレッドプールスレッドを取得し、渡されたデリゲートをそのスレッドで実行します。したがって、BeginInvokeを使用すると、.NET Frameworkは、新しいスレッドの作成、開始など、多くの作業を実行します。

ThreadPool.QueueUserWorkItem(delegate {/ * do stuff * /});も確認できます。非同期呼び出しへの代替アプローチ。

0
Aseem Gautam

実行時間の長いプロセス(フォームアプリケーション、IIS、Webサービス、Windowsサービスなど)がある場合は、非同期メソッドを使用したほうがよいでしょう。スレッドにはシステムリソースとオーバーヘッドが必要です。私は常にスレッドの作成を避けようとします。できない場合は、ThreadPoolを使用してそれらを処理/管理しようとします。

アプリケーションが何であるかを教えていただければ、より適切な情報が得られる可能性があります。

BeginInvokeは、Asyncメソッドが通常使用しないのに対し、舞台裏でデリゲートを使用します。