74

.NET のワーカー スレッドと I/O スレッドの詳細でありながら単純な説明を見つけるのは非常に困難です。

このトピックに関して私に明らかなこと(ただし、技術的に正確ではないかもしれません):

  • ワーカー スレッドは、作業に CPU を使用するスレッドです。
  • I/O スレッド (「完了ポート スレッド」とも呼ばれる)、デバイス ドライバーを使用して作業し、基本的に「何もしない」必要があり、CPU 以外の操作の完了のみを監視する必要があります。

不明な点:

  • メソッド ThreadPool.GetAvailableThreads は両方のタイプの使用可能なスレッドの数を返しますが、I/O スレッドの作業をスケジュールするパブリック API はないようです。.NET でワーカー スレッドを手動でのみ作成できますか?
  • 単一の I/O スレッドで複数の I/O 操作を監視できるようです。本当ですか?もしそうなら、ThreadPool がデフォルトで利用可能な I/O スレッドを非常に多く持っているのはなぜですか?
  • 一部のテキストでは、I/O スレッドによって I/O 操作の完了が実行された後にトリガーされるコールバックを読みました。本当ですか?このコールバックが CPU 操作であることを考えると、これはワーカー スレッドのジョブではないでしょうか。
  • より具体的に言えば、ASP.NET 非同期ページは I/O スレッドを使用しますか? ワーカー スレッドの最大数を増やすのではなく、I/O 作業を別のスレッドに切り替えることで、パフォーマンス上の利点は何ですか? 単一の I/O スレッドが複数の操作を監視しているためですか? または、I/O スレッドを使用すると、Windows はより効率的なコンテキスト切り替えを行いますか?
4

4 に答える 4

83

.net/CLR の「ワーカー スレッド」という用語は、通常、スレッドを生成したアプリケーションに代わって何らかの「作業」を行う、メイン スレッド以外のスレッドを指します。「作業」は、I/O が完了するのを待つことを含め、実際には何でも意味します。スレッドの作成にはコストがかかるため、ThreadPool はワーカー スレッドのキャッシュを保持します。

.net/CLR の「I/O スレッド」という用語は、「重複した」win32 呼び出し (「完了ポート I/O」とも呼ばれます) から NativeOverlapped コールバックをディスパッチするために ThreadPool が予約するスレッドを指します。CLR は独自の I/O 完了ポートを維持し、任意のハンドルをそれにバインドできます (ThreadPool.BindHandle API を使用)。例: http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx。多くの .net API は、このメカニズムを内部で使用して NativeOverlapped コールバックを受信しますが、通常の .net 開発者が直接使用することはありません。

「ワーカー スレッド」と「I/O スレッド」の間に技術的な違いはありません。どちらも単なる通常のスレッドです。ただし、CLR ThreadPool は、ワーカー スレッドに対する要求が高くなり、ネイティブ I/O コールバックのディスパッチに使用できるすべてのスレッドが使い果たされ、デッドロックが発生する可能性があるという状況を回避するために、それぞれのプールを個別に保持します。(250 個のワーカー スレッドをすべて使用するアプリケーションを想像してください。各スレッドは、何らかの I/O の完了を待機しています)。

開発者は、I/O スレッドが ThreadPool に確実に返されるように、I/O コールバックを処理するときに注意する必要があります。つまり、I/O コールバック コードは、コールバックを処理するために必要な最小限の作業を行う必要があります。次に、スレッドの制御を CLR スレッドプールに戻します。さらに作業が必要な場合は、その作業をワーカー スレッドでスケジュールする必要があります。そうしないと、アプリケーションが CLR の予約済み I/O 完了スレッドのプールを通常のワーカー スレッドとして使用するために「ハイジャック」し、上記のデッドロック状態に陥る危険があります。

さらに読むための参考文献: win32 I/O 完了ポート: http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx マネージド スレッドプール: http://msdn.microsoft.com /en-us/library/0ka9477y.aspx BindHandle の例: http://blogs.msdn.com/junfeng/archive/2008/12/01/threadpool-bindhandle.aspx

于 2010-01-30T17:34:12.670 に答える
12

まず、NT のプログラムで非同期 I/O がどのように使用されるかについて説明します。

ネイティブ API 関数NtReadFileのラッパーである Win32 API 関数ReadFile (例として) に精通しているかもしれません。この関数を使用すると、非同期 I/O で次の 2 つのことを行うことができます。

  • イベント オブジェクトを作成してNtReadFileに渡すことができます。このイベントは、読み取り操作が完了すると通知されます。
  • 非同期プロシージャ コール (APC) 関数をNtReadFileに渡すことができます。基本的にこれが意味することは、読み取り操作が完了すると、関数は操作を開始したスレッドのキューに入れられ、スレッドがアラート可能なwaitを実行するときに実行されるということです。

ただし、I/O 操作が完了したときに通知を受ける 3 つ目の方法があります。I/O 完了ポートオブジェクトを作成し、それにファイル ハンドルを関連付けることができます。I/O 完了ポートに関連付けられているファイルで操作が完了すると、操作の結果 (I/O ステータスなど) が I/O 完了ポートのキューに入れられます。次に、キューから結果を削除し、コールバック関数の呼び出しなどの適切なタスクを実行する専用スレッドを設定できます。これが本質的に「I/O ワーカー スレッド」です。

通常の「ワーカー スレッド」は非常に似ています。キューから I/O 結果を削除する代わりに、キューから作業項目を削除します。作業項目 ( QueueUserWorkItem ) をキューに入れ、ワーカー スレッドにそれらを実行させることができます。これにより、タスクを非同期で実行するたびにスレッドを生成する必要がなくなります。

于 2010-01-20T09:24:55.633 に答える
4

簡単に言えば、ワーカースレッドは短時間の作業を実行することを意味し、完了すると自動的に削除されます。コールバックは、親プロセスに完了したことを通知したり、データを返したりするために使用できます。

I / Oスレッドは、親プロセスによって停止されるまで、同じ操作または一連の操作を継続的に実行します。これは、通常、デバイスドライバがデバイスポートを継続的に監視するために実行されるため、このように呼ばれます。I / Oスレッドは通常、他のスレッドと通信したいときはいつでもイベントを作成します。

すべてのプロセスはスレッドとして実行されます。アプリケーションはスレッドとして実行されます。どのスレッドもワーカースレッドまたはI/Oスレッドを生成する可能性があります(あなたがそれらを呼ぶように)。

パフォーマンスと使用されるスレッドの数またはタイプの間には、常に微妙なバランスがあります。プロセスによって処理されるコールバックまたはイベントが多すぎると、処理中にメインプロセスループが中断される回数が増えるため、パフォーマンスが大幅に低下します。

ワーカースレッドの例としては、ユーザーの操作後にデータベースにデータを追加したり、長い数学的計算を実行したり、ファイルにデータを書き込んだりします。メインアプリケーションを解放するワーカースレッドを使用すると、タスクの実行中にフリーズしないため、これはGUIに最も役立ちます。

于 2010-01-20T08:49:38.180 に答える
1

私よりもスキルのある人がここに飛び込んで手伝ってくれます。

ワーカースレッドには多くの状態があり、プロセッサなどによってスケジュールされ、すべてを制御します。

IO 完了ポートは、共有状態がほとんどない非常に特殊なタスクのためにオペレーティング システムによって提供されるため、より高速に使用できます。.Net の良い例は、WCF フレームワークです。WCF サービスへのすべての "呼び出し" は、実際には IO Completion Port によって実行されます。これは、それらが最も高速に起動され、OS がそれらを処理するためです。

于 2010-01-20T09:13:29.607 に答える