Windows でのマネージド スレッド処理とアンマネージド スレッド処理

共通言語ランタイムにより作成されたスレッド、マネージド環境に入ってコードを実行するランタイム外部で作成されたスレッドなど、すべてのスレッドの管理は、 Thread クラスを使用して行われます。 ランタイムは、プロセス内のスレッドのうち、マネージド実行環境内でコードを実行したすべてのスレッドを監視します。 その他のスレッドは追跡しません。 ランタイムがマネージド オブジェクトを COM オブジェクトとしてアンマネージド環境に公開するため、スレッドは COM 相互運用を使用してマネージド実行環境に入ることができます。また、COM DllGetClassObject 関数やプラットフォーム呼び出しを介してマネージド実行環境に入ることもできます。

ただしアンマネージド スレッドが COM 呼び出し可能ラッパーなどを介してランタイムに入ると、システムがそのスレッド ローカル ストアで内部マネージド Thread オブジェクトを検索します。 このオブジェクトが見つかった場合、ランタイムは既にこのスレッドを認識しています。 見つからない場合、ランタイムは新しい Thread オブジェクトを作成し、そのスレッドのスレッド ローカル ストアにインストールします。

マネージド スレッド処理では、 Thread.GetHashCode は安定したマネージド スレッド ID です。 この値は、取得されたアプリケーション ドメインに関係なく、スレッドの有効期間にわたって他のスレッドの値と競合することはありません。

Win32 スレッド処理とマネージド スレッド処理の対応付け

Win32 スレッド処理要素とほぼそれに対応するランタイムの対応付けを次の表に示します。 この対応付けは、同一の機能性を示すものではありません。 たとえば TerminateThreadfinally 句の実行やリソースの解放は行わず、また防止することはできません。 ただし Thread.Abort はすべてのロールバック コードを実行し、すべてのリソースを解放します。また、 ResetAbortを使用して拒否することができます。 機能について推測する前に、このドキュメントを詳しくお読みください。

Win32 共通言語ランタイム
CreateThread ThreadThreadStartの組み合わせ
TerminateThread Thread.Abort
SuspendThread Thread.Suspend
ResumeThread Thread.Resume
Sleep Thread.Sleep
スレッド ハンドルのWaitForSingleObject Thread.Join
ExitThread 同等の機能がありません
GetCurrentThread Thread.CurrentThread
SetThreadPriority Thread.Priority
同等の機能がありません Thread.Name
同等の機能がありません Thread.IsBackground
CoInitializeEx (OLE32.DLL) に類似 Thread.ApartmentState

マネージド スレッドと COM アパートメント

マネージド スレッドには、シングル スレッド アパートメントをホストするか、マルチ スレッド アパートメントをホストするかを示すようマークすることができます (COM スレッド アーキテクチャの詳細については、「Processes, Threads, and Apartments」(プロセス、スレッド、アパートメント) を参照してください。)GetApartmentState クラスの SetApartmentStateTrySetApartmentState、および Thread の各スレッドは、スレッドのアパートメント状態を返して割り当てます。 状態が設定されていない場合、GetApartmentStateApartmentState.Unknown を返します。

プロパティは、スレッドが ThreadState.Unstarted 状態の場合にのみ設定することができます。設定できるのは、1 つのスレッドにつき 1 回だけです。

スレッド開始前にアパートメントの状態が設定されていない場合、このスレッドはマルチスレッド アパートメント (MTA) として初期化されます。 ファイナライザー スレッドと、 ThreadPool により制御されるすべてのスレッドは MTA です。

重要

アプリケーションのスタートアップ コードでは、アパートメントの状態を制御する方法は、 MTAThreadAttribute または STAThreadAttribute をエントリ ポイント プロシージャに適用する方法だけです。

COM に対して公開されるマネージド オブジェクトは、フリー スレッド マーシャラーを集約した場合と同様に動作します。 つまり、フリースレッドな方法ですべての COM アパートメントから呼び出すことができます。 このフリー スレッドな動作を示さないマネージド オブジェクトは、ServicedComponent または StandardOleMarshalObject から派生したオブジェクトだけです。

マネージ環境では、コンテキストおよびコンテキストにバインディングされたマネージド インスタンスを使用しない場合には SynchronizationAttribute はサポートされません。 Enterprise Services を使う場合は、オブジェクトを ServicedComponent (ContextBoundObject から派生したオブジェクト) から派生する必要があります。

マネージド コードは、COM オブジェクトを呼び出すときには常に COM 規則に従います。 つまり、OLE32 によって示される COM アパートメント プロキシと COM+ 1.0 コンテキスト ラッパーを介して呼び出します。

障害となっている問題点

アンマネージ コードでスレッドをブロックしているオペレーティング システムに対し、そのスレッドがアンマネージ呼び出しを実行する場合、ランタイムは Thread.Interrupt または Thread.Abortに対してその呼び出しを制御しません。 Thread.Abortでは、スレッドが再びマネージド コードに入ると、ランタイムはスレッドを Abort 対象としてマークし、スレッドを制御します。 アンマネージド ブロックではなくマネージド ブロックを使用することをお勧めします。 WaitHandle.WaitOneWaitHandle.WaitAnyWaitHandle.WaitAllMonitor.EnterMonitor.TryEnterThread.JoinGC.WaitForPendingFinalizers などはすべて、Thread.InterruptThread.Abort に応答します。 また、スレッドがシングルスレッド アパート内にある場合、これらのマネージド ブロック操作はすべて、スレッドがブロックされている間でもアパートメント内で正しくメッセージ ポンプを行います。

スレッドとファイバー

.NET スレッド モデルでは、ファイバーがサポートされていません。 ファイバーの使用により実装されるアンマネージド関数を呼び出さないでください。 呼び出すと、.NET ランタイムがクラッシュする可能性があります。

関連項目