回答:
GetThreadId
指定されたネイティブスレッドのIDを返します。マネージスレッドで機能させる方法はいくつかあります。きっと、スレッドハンドルを見つけてその関数に渡すだけです。
GetCurrentThreadId
現在のスレッドのIDを返します。
GetCurrentThreadId
.NET 2.0で非推奨になりました。推奨される方法はThread.CurrentThread.ManagedThreadId
プロパティです。
System.Threading.Thread.CurrentThread.ManagedThreadId
、少なくともで使用すると機能しないことに注意してくださいSetWindowsHookEx
。代わりに、ネイティブのwin32関数からスレッドIDを取得する必要がありますGetCurrentThreadId()
。
たとえば、C#では、スレッドをデバッグするときに、各スレッドのIDを確認できます。
これは、管理対象スレッドのIDになります。 ManagedThreadId
のメンバーなThread
ので、任意のThreadオブジェクトからIDを取得できます。これにより、現在のManagedThreadIDが取得されます。
Thread.CurrentThread.ManagedThreadId
OSスレッドID (ManagedThreadIDではない)でOSスレッドを取得するには、linqを少し試してみます。
int unmanagedId = 2345;
ProcessThread myThread = (from ProcessThread entry in Process.GetCurrentProcess().Threads
where entry.Id == unmanagedId
select entry).First();
マネージスレッドを列挙する方法はなく、ProcessThreadとThreadの関係もないようです。そのため、マネージスレッドをIDで取得するのは難しいものです。
マネージスレッドとアンマネージスレッドの詳細については、このMSDNアークティックスを参照してください。
廃止予定AppDomain.GetCurrentThreadId
を使用して、現在実行中のスレッドのIDを取得できます。このメソッドは、Win32 APIメソッドへのPInvokeを使用しGetCurrentThreadID
、WindowsスレッドIDを返します。
.NETスレッドオブジェクトが単一のWindowsスレッドに対応せず、特定の.NETスレッドに対してWindowsから返される可能性のある安定したIDがないため、このメソッドは非推奨としてマークされています。
これが事実である理由の詳細については、コンフィギュレーターの回答を参照してください。
OS IDを取得するには:
AppDomain.GetCurrentThreadId()
AppDomain.GetCurrentThreadId()
は廃止AppDomain.GetCurrentThreadId
されましたfibers (aka lightweight threads)
。マネージスレッドがで実行されているときに安定したIDを提供しないため、廃止されました。マネージスレッドの安定した識別子を取得するには、のManagedThreadId
プロパティを使用しますThread
。使用法:Thread.CurrentThread.ManagedThreadId
MSDNによると:
非管理対象ホストは管理対象スレッドと非管理対象スレッドの関係を制御できるため、オペレーティングシステムのThreadIdと管理対象スレッドとの間に固定の関係はありません。具体的には、高度なホストはCLR Hosting APIを使用して、同じオペレーティングシステムスレッドに対して多くのマネージスレッドをスケジュールしたり、マネージスレッドを異なるオペレーティングシステムスレッド間で移動したりできます。
したがって、基本的に、Thread
オブジェクトは必ずしもOSスレッドに対応しているわけではありません。そのため、ネイティブIDが公開されていません。
ハッキングしようとしている人のために:
public static int GetNativeThreadId(Thread thread)
{
var f = typeof(Thread).GetField("DONT_USE_InternalThread",
BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
var pInternalThread = (IntPtr)f.GetValue(thread);
var nativeId = Marshal.ReadInt32(pInternalThread, (IntPtr.Size == 8) ? 548 : 348); // found by analyzing the memory
return nativeId;
}
現在のスレッドIDを見つけるには、「Thread.CurrentThread.ManagedThreadId」を使用します。ただし、この場合、現在のwin32スレッドIDが必要になる可能性があります。この関数で取得するには、pInvokeを使用します。
[DllImport("Kernel32", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
public static extern Int32 GetCurrentWin32ThreadId();
最初に、マネージスレッドIDとwin32スレッドID接続を保存する必要があります-win32 IDをマネージスレッドにマップする辞書を使用します。
次に、IDでスレッドを見つけるには、Process.GetCurrentProcess()。Threadsを使用してプロセスのスレッドを反復処理し、そのIDのスレッドを見つけます。
foreach (ProcessThread thread in Process.GetCurrentProcess().Threads)
{
var managedThread = win32ToManagedThread[thread.id];
if((managedThread.ManagedThreadId == threadId)
{
return managedThread;
}
}
ProcessThread
、これはと同じではありません、オブジェクトを(またそれを継承しています)Thread
:(thread as Thread)
nullの参照を返します。
Windows 10でのオフセットは0x022C(x64-bit-Application)と0x0160(x32-bit-Application)です。
public static int GetNativeThreadId(Thread thread)
{
var f = typeof(Thread).GetField("DONT_USE_InternalThread",
BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance);
var pInternalThread = (IntPtr)f.GetValue(thread);
var nativeId = Marshal.ReadInt32(pInternalThread, (IntPtr.Size == 8) ? 0x022C : 0x0160); // found by analyzing the memory
return nativeId;
}
マネージコードからThread
、各マネージスレッドのタイプのインスタンスにアクセスできます。Thread
OSスレッドの概念をカプセル化し、現在のCLR以降、マネージスレッドおよびOSスレッドと1対1で対応しています。ただし、これは実装の詳細であり、将来変更される可能性があります。
Visual Studioによって表示されるIDは、実際にはOSスレッドIDです。これはない、いくつかの回答により示唆されるように管理するスレッドIDと同じ。
Thread
タイプと呼ばれる民間のIntPtrメンバーフィールド含まれていDONT_USE_InternalThread
た点を基本的なOS構造にし、。ただし、これは実際の実装の詳細であるため、このIMOを追求することはお勧めできません。そして、一種の名前は、これに依存すべきではないことを示しています。
マネージスレッドIDを返すThread.GetHashCodeを使用できます。GetHashCodeの目的を考えると、これは理にかなっています。オブジェクト(スレッド)の一意の識別子(たとえば、辞書のキー)である必要があります。
Threadクラスの参照ソースは、ここで参考になります。(確かに、特定の.NET実装はこのソースコードに基づいていない可能性がありますが、デバッグの目的で私はチャンスを利用します。)
GetHashCodeは、「オブジェクトの等価性の迅速なチェックが必要なアルゴリズムにこのハッシュコードを提供する」ため、スレッドの等価性のチェックに適しています。たとえば、特定のメソッドが呼び出し元のスレッドで実行されていることをアサートする場合などです。