プロセス、スレッド、およびアパートメント
プロセス は、仮想メモリ領域、コード、データ、およびシステム リソースのコレクションです。 スレッド は、プロセス内で順次実行されるコードです。 プロセッサはプロセスではなくスレッドを実行するため、各アプリケーションには少なくとも 1 つのプロセスがあり、プロセスには常に少なくとも 1 つの実行スレッド (プライマリ スレッドと呼ばれます) があります。 プロセスには、プライマリ スレッドに加えて複数のスレッドを含めることができます。
プロセスは、Microsoft のリモート プロシージャ コール (RPC) テクノロジを使用してメッセージを介して相互に通信し、相互に情報を渡します。 リモート コンピューター上のプロセスからの呼び出しと、同じコンピューター上の別のプロセスからの呼び出しとの間で、呼び出し元に違いはありません。
スレッドの実行が開始されると、スレッドが強制終了されるまで、または優先度の高いスレッドによって中断されるまで (ユーザー アクションまたはカーネルのスレッド スケジューラによって) 続行されます。 各スレッドは、コードの個別のセクションを実行することも、複数のスレッドで同じコード セクションを実行することもできます。 同じコード ブロックを実行するスレッドは、個別のスタックを維持します。 プロセス内の各スレッドは、そのプロセスのグローバル変数とリソースを共有します。
スレッド スケジューラは、プロセスの優先度クラス属性とスレッドの基本優先度の組み合わせに従って、スレッドを実行するタイミングと頻度を決定します。 SetPriorityClass 関数を呼び出してプロセスの優先度クラス属性を設定し、SetThreadPriorityを呼び出してスレッドの基本優先度設定します。
マルチスレッド アプリケーションでは、2 つのスレッド処理の問題を回避する必要があります。デッドロック と競合 します。 デッドロックは、各スレッドが他のスレッドが何かを行うのを待っているときに発生します。 COM 呼び出し制御は、オブジェクト間の呼び出しでデッドロックを防ぐのに役立ちます。 競合状態は、あるスレッドが依存する別のスレッドの前に終了したときに発生し、後者がまだ有効な値を提供していないため、前者が初期化されていない値を使用します。 COM には、アウトプロセス サーバーでの競合状態を回避するために特別に設計された関数がいくつか用意されています。 (プロセス外サーバー実装ヘルパー を参照してください)。
アパートメントと COM スレッド アーキテクチャ
COM では、複数のスレッドの実行が導入される前に広く普及している単一スレッドのプロセスごとのモデルがサポートされていますが、複数のスレッドを利用するコードを記述できます。その結果、1 つのスレッドを実行し、別のスレッドが時間のかかる操作が完了するのを待機することで、アプリケーションの効率が向上します。
手記
複数のスレッドを使用することは、パフォーマンスの向上を保証するものではありません。 実際、スレッド ファクターは困難な問題であるため、複数のスレッドを使用するとパフォーマンスの問題が発生することがよくあります。 重要なのは、あなたが何をしているのか非常に確信している場合にのみ、複数のスレッドを使用することです。
一般に、COM スレッド アーキテクチャを表示する最も簡単な方法は、プロセス内のすべての COM オブジェクトを、アパートメントと呼ばれるグループに分けて考える方法です。 COM オブジェクトは、そのメソッドは、そのアパートメントに属するスレッドによってのみ直接呼び出すことができるという意味で、厳密に 1 つのアパートメントに存在します。 オブジェクトを呼び出すその他のスレッドは、プロキシを経由する必要があります。
アパートメントには、シングルスレッドアパートメント 、マルチスレッドアパートメント の2種類があります。
- シングル スレッド アパートメントは 1 つのスレッドで構成されるため、シングルスレッド アパートメントに存在するすべての COM オブジェクトは、そのアパートメントに属する 1 つのスレッドからのみメソッド呼び出しを受け取ることができます。 シングルスレッド アパートメント内の COM オブジェクトに対するすべてのメソッド呼び出しは、シングルスレッド アパートメントのスレッドの Windows メッセージ キューと同期されます。 単一の実行スレッドを持つプロセスは、このモデルの特殊なケースにすぎません。
- マルチスレッド アパートメントは 1 つ以上のスレッドで構成されるため、マルチスレッド アパートメントに存在するすべての COM オブジェクトは、マルチスレッド アパートメントに属するスレッドからメソッド呼び出しを直接受け取ることができます。 マルチスレッド アパートメント内のスレッドは、フリー スレッドと呼ばれるモデルを使用します。 マルチスレッド アパートメント内の COM オブジェクトの呼び出しは、オブジェクト自体によって同期されます。
手記
同じプロセス内のシングル スレッド アパートメントとマルチスレッド アパートメント間の通信の詳細については、「Single-Threaded とマルチスレッド通信」を参照してください。
プロセスには、0 個以上のシングル スレッド アパートメントと、0 個または 1 つのマルチスレッド アパートメントを含めることができます。
プロセスでは、メイン アパートメントが最初に初期化されます。 シングルスレッドプロセスでは、これが唯一のアパートです。 呼び出しパラメーターはアパートメント間でマーシャリングされ、COM はメッセージングを介して同期を処理します。 プロセス内の複数のスレッドをフリー スレッドに指定した場合、すべての空きスレッドは 1 つのアパートメントに存在し、パラメーターはアパートメント内の任意のスレッドに直接渡され、すべての同期を処理する必要があります。 フリースレッディングとアパートメントスレッディングの両方のプロセスでは、すべての無料スレッドが単一のアパートに存在し、他のすべてのアパートメントはシングルスレッドアパートメントです。 COM の作業を行うプロセスは、最大で 1 つのマルチスレッド アパートメントを持つアパートメントのコレクションですが、シングルスレッド アパートメントはいくつでも使用できます。
COM のスレッド モデルは、異なるスレッド アーキテクチャを使用するクライアントとサーバーが連携するメカニズムを提供します。 異なるプロセスで異なるスレッド モデルを持つオブジェクト間の呼び出しは、当然ながらサポートされます。 呼び出し元オブジェクトの観点からは、呼び出されるオブジェクトがスレッド化されている方法に関係なく、プロセス外のオブジェクトに対するすべての呼び出しは同じように動作します。 同様に、呼び出されるオブジェクトの観点からは、呼び出し元のスレッド モデルに関係なく、着信呼び出しは同じように動作します。
クライアントとオブジェクトが異なるプロセスにあるため、異なるスレッド モデルを使用する場合でも、クライアントとアウトプロセス オブジェクトの間の相互作用は簡単です。 クライアントとサーバーの間に介在する COM は、標準のマーシャリングと RPC を使用して、スレッド モデルが相互運用するためのコードを提供できます。 たとえば、シングル スレッド オブジェクトが複数のフリー スレッド クライアントによって同時に呼び出される場合、呼び出しは、対応するウィンドウ メッセージをサーバーのメッセージ キューに配置することによって COM によって同期されます。 オブジェクトのアパートメントは、メッセージを取得してディスパッチするたびに 1 つの呼び出しを受け取ります。 ただし、インプロセス サーバーがクライアントと正しく対話するように注意する必要があります。 (In-Process サーバースレッドの問題を参照してください)。
マルチスレッド モデルを使用したプログラミングにおける最も重要な問題は、特定のスレッドを対象としたメッセージがそのスレッドにのみ送信され、スレッドへのアクセスが保護されるように、コードをスレッドセーフにすることです。
詳細については、次のトピックを参照してください。
- スレッド モデル の選択
- Single-Threaded アパートメンツ
- マルチスレッド アパートメント
- Single-Threaded とマルチスレッド通信
- In-Process サーバースレッドの問題
- アパートメント間のインターフェイスへのアクセス