Windows でのマネージド スレッド処理とアンマネージド スレッド処理Managed and unmanaged threading in Windows

共通言語ランタイムにより作成されたスレッド、マネージド環境に入ってコードを実行するランタイム外部で作成されたスレッドなど、すべてのスレッドの管理は、 Thread クラスを使用して行われます。Management of all threads is done through the Thread class, including threads created by the common language runtime and those created outside the runtime that enter the managed environment to execute code. ランタイムは、プロセス内のスレッドのうち、マネージド実行環境内でコードを実行したすべてのスレッドを監視します。The runtime monitors all the threads in its process that have ever executed code within the managed execution environment. その他のスレッドは追跡しません。It does not track any other threads. ランタイムがマネージド オブジェクトを COM オブジェクトとしてアンマネージド環境に公開するため、スレッドは COM 相互運用を使用してマネージド実行環境に入ることができます。また、COM DllGetClassObject 関数やプラットフォーム呼び出しを介してマネージド実行環境に入ることもできます。Threads can enter the managed execution environment through COM interop (because the runtime exposes managed objects as COM objects to the unmanaged world), the COM DllGetClassObject function, and platform invoke.

ただしアンマネージド スレッドが COM 呼び出し可能ラッパーなどを介してランタイムに入ると、システムがそのスレッド ローカル ストアで内部マネージド Thread オブジェクトを検索します。When an unmanaged thread enters the runtime through, for example, a COM callable wrapper, the system checks the thread-local store of that thread to look for an internal managed Thread object. このオブジェクトが見つかった場合、ランタイムは既にこのスレッドを認識しています。If one is found, the runtime is already aware of this thread. 見つからない場合、ランタイムは新しい Thread オブジェクトを作成し、そのスレッドのスレッド ローカル ストアにインストールします。If it cannot find one, however, the runtime builds a new Thread object and installs it in the thread-local store of that thread.

マネージド スレッド処理では、 Thread.GetHashCode は安定したマネージド スレッド ID です。In managed threading, Thread.GetHashCode is the stable managed thread identification. この値は、取得されたアプリケーション ドメインに関係なく、スレッドの有効期間にわたって他のスレッドの値と競合することはありません。For the lifetime of your thread, it will not collide with the value from any other thread, regardless of the application domain from which you obtain this value.

注意

オペレーティング システム ThreadId とマネージド スレッドの間には固定的な関係はありません。これは、アンマネージド ホストがマネージド スレッドとアンマネージド スレッドの間の関係を制御できるためです。An operating-system ThreadId has no fixed relationship to a managed thread, because an unmanaged host can control the relationship between managed and unmanaged threads. 特に、高度なホストはファイバー API を使用して、多数のマネージド スレッドを同一オペレーティング システム スレッドに対してスケジュールしたり、マネージド スレッドを異なるオペレーティング システム スレッド間で移動したりできます。Specifically, a sophisticated host can use the Fiber API to schedule many managed threads against the same operating system thread, or to move a managed thread among different operating system threads.

Win32 スレッド処理とマネージド スレッド処理の対応付けMapping from Win32 threading to managed threading

Win32 スレッド処理要素とほぼそれに対応するランタイムの対応付けを次の表に示します。The following table maps Win32 threading elements to their approximate runtime equivalent. この対応付けは、同一の機能性を示すものではありません。Note that this mapping does not represent identical functionality. たとえば TerminateThreadfinally 句の実行やリソースの解放は行わず、また防止することはできません。For example, TerminateThread does not execute finally clauses or free up resources, and cannot be prevented. ただし Thread.Abort はすべてのロールバック コードを実行し、すべてのリソースを解放します。また、 ResetAbortを使用して拒否することができます。However, Thread.Abort executes all your rollback code, reclaims all the resources, and can be denied using ResetAbort. 機能について推測する前に、このドキュメントを詳しくお読みください。Be sure to read the documentation closely before making assumptions about functionality.

Win32In Win32 共通言語ランタイムIn the common language runtime
CreateThreadCreateThread ThreadThreadStartの組み合わせCombination of Thread and ThreadStart
TerminateThreadTerminateThread Thread.Abort
SuspendThreadSuspendThread Thread.Suspend
ResumeThreadResumeThread Thread.Resume
SleepSleep Thread.Sleep
スレッド ハンドルのWaitForSingleObjectWaitForSingleObject on the thread handle Thread.Join
ExitThreadExitThread 同等の機能がありませんNo equivalent
GetCurrentThreadGetCurrentThread Thread.CurrentThread
SetThreadPrioritySetThreadPriority Thread.Priority
同等の機能がありませんNo equivalent Thread.Name
同等の機能がありませんNo equivalent Thread.IsBackground
CoInitializeEx (OLE32.DLL) に類似Close to CoInitializeEx (OLE32.DLL) Thread.ApartmentState

マネージド スレッドと COM アパートメントManaged threads and COM apartments

マネージド スレッドには、シングル スレッド アパートメントをホストするか、マルチ スレッド アパートメントをホストするかを示すようマークすることができますA managed thread can be marked to indicate that it will host a single-threaded or multithreaded apartment. (COM スレッド アーキテクチャの詳細については、「Processes, Threads, and Apartments」(プロセス、スレッド、アパートメント) を参照してください。)GetApartmentState クラスの SetApartmentStateTrySetApartmentState、および Thread の各スレッドは、スレッドのアパートメント状態を返して割り当てます。(For more information on the COM threading architecture, see Processes, Threads, and Apartments.) The GetApartmentState, SetApartmentState, and TrySetApartmentState methods of the Thread class return and assign the apartment state of a thread. 状態が設定されていない場合、GetApartmentStateApartmentState.Unknown を返します。If the state has not been set, GetApartmentState returns ApartmentState.Unknown.

プロパティは、スレッドが ThreadState.Unstarted 状態の場合にのみ設定することができます。設定できるのは、1 つのスレッドにつき 1 回だけです。The property can be set only when the thread is in the ThreadState.Unstarted state; it can be set only once for a thread.

スレッド開始前にアパートメントの状態が設定されていない場合、このスレッドはマルチスレッド アパートメント (MTA) として初期化されます。If the apartment state is not set before the thread is started, the thread is initialized as a multithreaded apartment (MTA). ファイナライザー スレッドと、 ThreadPool により制御されるすべてのスレッドは MTA です。The finalizer thread and all threads controlled by ThreadPool are MTA.

重要

アプリケーションのスタートアップ コードでは、アパートメントの状態を制御する方法は、 MTAThreadAttribute または STAThreadAttribute をエントリ ポイント プロシージャに適用する方法だけです。For application startup code, the only way to control apartment state is to apply the MTAThreadAttribute or the STAThreadAttribute to the entry point procedure. .NET Framework 1.0 と 1.1 では、 ApartmentState プロパティを最初のコード行として設定できます。In the .NET Framework 1.0 and 1.1, the ApartmentState property can be set as the first line of code. .NET Framework 2.0 ではこの設定は許可されていません。This is not permitted in the .NET Framework 2.0.

COM に対して公開されるマネージド オブジェクトは、フリー スレッド マーシャラーを集約した場合と同様に動作します。Managed objects that are exposed to COM behave as if they had aggregated the free-threaded marshaler. つまり、フリースレッドな方法ですべての COM アパートメントから呼び出すことができます。In other words, they can be called from any COM apartment in a free-threaded manner. このフリー スレッドな動作を示さないマネージド オブジェクトは、ServicedComponent または StandardOleMarshalObject から派生したオブジェクトだけです。The only managed objects that do not exhibit this free-threaded behavior are those objects that derive from ServicedComponent or StandardOleMarshalObject.

マネージ環境では、コンテキストおよびコンテキストにバインディングされたマネージド インスタンスを使用しない場合には SynchronizationAttribute はサポートされません。In the managed world, there is no support for the SynchronizationAttribute unless you use contexts and context-bound managed instances. Enterprise Services を使う場合は、オブジェクトを ServicedComponent (ContextBoundObject から派生したオブジェクト) から派生する必要があります。If you are using Enterprise Services, then your object must derive from ServicedComponent (which is itself derived from ContextBoundObject).

マネージド コードは、COM オブジェクトを呼び出すときには常に COM 規則に従います。When managed code calls out to COM objects, it always follows COM rules. つまり、OLE32 によって示される COM アパートメント プロキシと COM+ 1.0 コンテキスト ラッパーを介して呼び出します。In other words, it calls through COM apartment proxies and COM+ 1.0 context wrappers as dictated by OLE32.

障害となっている問題点Blocking issues

アンマネージ コードでスレッドをブロックしているオペレーティング システムに対し、そのスレッドがアンマネージ呼び出しを実行する場合、ランタイムは Thread.Interrupt または Thread.Abortに対してその呼び出しを制御しません。If a thread makes an unmanaged call into the operating system that has blocked the thread in unmanaged code, the runtime will not take control of it for Thread.Interrupt or Thread.Abort. Thread.Abortでは、スレッドが再びマネージド コードに入ると、ランタイムはスレッドを Abort 対象としてマークし、スレッドを制御します。In the case of Thread.Abort, the runtime marks the thread for Abort and takes control of it when it re-enters managed code. アンマネージド ブロックではなくマネージド ブロックを使用することをお勧めします。It is preferable for you to use managed blocking rather than unmanaged blocking. WaitHandle.WaitOneWaitHandle.WaitAny, WaitHandle.WaitAll, Monitor.Enter, Monitor.TryEnter, Thread.Join, GC.WaitForPendingFinalizersなどはすべて Thread.InterruptThread.Abortに応答します。WaitHandle.WaitOne,WaitHandle.WaitAny, WaitHandle.WaitAll, Monitor.Enter, Monitor.TryEnter, Thread.Join, GC.WaitForPendingFinalizers, and so on are all responsive to Thread.Interrupt and to Thread.Abort. また、スレッドがシングルスレッド アパート内にある場合、これらのマネージド ブロック操作はすべて、スレッドがブロックされている間でもアパートメント内で正しくメッセージ ポンプを行います。Also, if your thread is in a single-threaded apartment, all these managed blocking operations will correctly pump messages in your apartment while your thread is blocked.

スレッドとファイバーThreads and fibers

.NET スレッド モデルでは、ファイバーがサポートされていません。The .NET threading model does not support fibers. ファイバーの使用により実装されるアンマネージド関数を呼び出さないでください。You should not call into any unmanaged function that is implemented by using fibers. 呼び出すと、.NET ランタイムがクラッシュする可能性があります。Such calls may result in a crash of the .NET runtime.

関連項目See also