プロセス、スレッド、およびアパートメント

プロセスは、仮想メモリ領域、コード、データ、およびシステム リソースのコレクションです。 スレッドとは、プロセス内で順次実行されるコードです。 プロセッサはプロセスではなくスレッドを実行するため、各アプリケーションには少なくとも 1 つのプロセスがあり、プロセスには常に少なくとも 1 つの実行スレッド (プライマリ スレッドと呼ばれます) があります。 プロセスには、プライマリ スレッドに加えて複数のスレッドを含めることができます。

プロセスは、Microsoft のリモート プロシージャ コール (RPC) テクノロジを使用してメッセージを介して相互に通信し、相互に情報を渡します。 リモート コンピューター上のプロセスからの呼び出しと、同じコンピューター上の別のプロセスからの呼び出しとの間で、呼び出し元に違いはありません。

スレッドの実行が開始されると、スレッドが強制終了されるまで、または優先度の高いスレッドによって中断されるまで (ユーザー アクションまたはカーネルのスレッド スケジューラによって) 続行されます。 各スレッドは、コードの個別のセクションを実行することも、複数のスレッドで同じコード セクションを実行することもできます。 同じコード ブロックを実行するスレッドメイン個別のスタックが含まれます。 プロセス内の各スレッドは、そのプロセスのグローバル変数とリソースを共有します。

スレッド スケジューラは、プロセスの優先度クラス属性とスレッドの基本優先度の組み合わせに従って、スレッドを実行するタイミングと頻度を決定します。 SetPriorityClass 関数を呼び出してプロセスの優先度クラス属性を設定し、SetThreadPriority の呼び出しでスレッドの基本優先度を設定します。

マルチスレッド アプリケーションでは、デッドロック競合という 2 つのスレッドの問題を回避する必要があります。 デッドロックは、各スレッドが他のスレッドが何かを行うのを待っているときに発生します。 COM 呼び出し制御は、オブジェクト間の呼び出しでデッドロックを防ぐのに役立ちます。 競合状態は、あるスレッドが依存する別のスレッドより先に終了し、後者がまだ有効な値を提供していないため、前者が初期化されていない値を使用する場合に発生します。 COM には、アウトプロセス サーバーでの競合状態を回避するために特別に設計された関数がいくつか用意されています。 (アウトプロセス サーバー実装ヘルパーを参照してください。)

アパートメントと COM スレッド アーキテクチャ

COM は、マルチスレッド実行が導入される前に一般的であったプロセスごとのシングルスレッド モデルをサポートしていますが、あるスレッドが実行されている間、別のスレッドが時間のかかる処理の完了を待つようにすることで、マルチスレッドを利用するコードを書くことができ、より効率的なアプリケーションを実現できます。

Note

複数のスレッドを使用することは、パフォーマンスの向上を保証するものではありません。 実際、スレッド ファクターは困難な問題であるため、複数のスレッドを使用するとパフォーマンスの問題が発生することがよくあります。 重要なのは、あなたが何をしているのか非常に確信している場合にのみ、複数のスレッドを使用することです。

 

一般に、COM スレッド アーキテクチャを表示する最も簡単な方法は、プロセス内のすべての COM オブジェクトをアパートメントと呼ばれるグループに分けて考える方法です。 COM オブジェクトは、そのアパートメントに属するスレッドによってのみ合法的にメソッドを直接呼び出すことができるという意味で、厳密に 1 つのアパートメント内に存在します。 オブジェクトを呼び出すその他のスレッドは、プロキシを経由する必要があります。

アパートメントには、シングルスレッド アパートメントマルチスレッド アパートメントの 2 種類があります。

  • シングルスレッド アパートメントは 1 つのスレッドで構成されているため、シングルスレッド アパートメント内に存在するすべての COM オブジェクトは、そのアパートメントに属する 1 つのスレッドからのみメソッド呼び出しを受け取ることができます。 シングルスレッド アパートメント内の COM オブジェクトに対するすべてのメソッド呼び出しは、シングルスレッド アパートメントのスレッドの Windows メッセージ キューと同期されます。 単一の実行スレッドを持つプロセスは、このモデルの特殊なケースにすぎません。
  • マルチスレッド アパートメントは 1 つ以上のスレッドで構成されているため、マルチスレッド アパートメント内に存在するすべての COM オブジェクトは、マルチスレッド アパートメントに属する任意のスレッドからメソッド呼び出しを直接受け取ることができます。 マルチスレッド アパートメント内のスレッドは、フリー スレッドと呼ばれるモデルを使用します。 マルチスレッド アパートメント内の COM オブジェクトの呼び出しは、オブジェクト自体によって同期されます。

Note

同じプロセス内のシングルスレッド アパートメントとマルチスレッド アパートメント間の通信の詳細については、「シングルスレッド通信とマルチスレッド通信」を参照してください。

 

プロセスには、0 個以上のシングルスレッド アパートメントと、0 個または 1 つのマルチスレッド アパートメントを含めることができます。

プロセスでは、メイン アパートメントが最初に初期化されます。 シングルスレッド プロセスでは、これが唯一のアパートです。 呼び出しパラメーターはアパートメント間でマーシャリングされ、COM はメッセージングを通じて同期を処理します。 プロセス内の複数のスレッドをフリースレッドに指定すると、すべてのフリースレッドが 1 つのアパートメントに存在し、パラメーターがアパートメント内の任意のスレッドに直接渡され、すべての同期を処理する必要があります。 フリー スレッドとアパートメント スレッドの両方を使用するプロセスでは、すべてのフリー スレッドは 1 つのアパートメントに存在し、他のすべてのアパートメントはシングルスレッド アパートメントになります。 COM の作業を行うプロセスは、最大でも 1 つのマルチスレッド アパートメントを含むアパートメントのコレクションですが、任意の数のシングルスレッド アパートメントを含めることができます。

COM のスレッド モデルは、異なるスレッド アーキテクチャを使用するクライアントとサーバーが連携するメカニズムを提供します。 異なるプロセスで異なるスレッド モデルを持つオブジェクト間の呼び出しは、当然ながらサポートされます。 呼び出し元オブジェクトの観点から見ると、呼び出されるオブジェクトがどのようにスレッド化されているかに関係なく、プロセス外のオブジェクトへのすべての呼び出しは同じように動作します。 同様に、呼び出されるオブジェクトの観点からは、呼び出し元のスレッド モデルに関係なく、到着する呼び出しは同じように動作します。

クライアントとアウトプロセス オブジェクト間の対話は、クライアントとオブジェクトが異なるプロセスにあるため、異なるスレッド モデルを使用している場合でも簡単です。 クライアントとサーバーの間に介在する COM は、標準のマーシャリングと RPC を使用して、相互運用するためのスレッド モデルのコードを提供できます。 たとえば、シングルスレッド オブジェクトが複数のフリー スレッド クライアントによって同時に呼び出された場合、その呼び出しは、対応するウィンドウ メッセージをサーバーのメッセージ キューに配置することによって COM によって同期されます。 オブジェクトのアパートメントは、メッセージを取得してディスパッチするたびに 1 つの呼び出しを受け取ります。 ただし、インプロセス サーバーがクライアントと正しく対話するように注意する必要があります。 (「インプロセス サーバーのスレッドの問題」を参照してください。)

マルチスレッド モデルを使用したプログラミングにおける最も重要な問題は、コードをスレッドセーフにして、特定のスレッド向けのメッセージがそのスレッドにのみ送信され、スレッドへのアクセスが保護されるようにすることです。

詳細については、次のトピックを参照してください。