たとえばC#では、スレッドのデバッグ時に、各スレッドのIDを確認できます。
私はプログラム的に同じスレッドを取得する方法を見つけることができませんでした。現在のスレッドのIDを取得することさえできませんでした(Thread.currentThread
のプロパティ内)。
それで、Visual StudioはどのようにスレッドのIDを取得するのでしょうか。たとえば、id 2345
のスレッドのハンドルを取得する方法はありますか。
GetThreadId
は、指定されたネイティブスレッドのIDを返します。マネージスレッドで動作させる方法はいくつかあります。スレッドハンドルだけを見つけてそれをその関数に渡すことだけが必要です。
GetCurrentThreadId
は現在のスレッドのIDを返します。
GetCurrentThreadId
は.NET 2.0以降では推奨されていません。推奨される方法は Thread.CurrentThread.ManagedThreadId
プロパティです。
たとえばC#では、スレッドのデバッグ時に、各スレッドのIDを確認できます。
これが管理対象スレッドのIDになります。 ManagedThreadId
はThread
のメンバーなので、任意の Thread objectから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の記事 を参照してください。
現在実行中のスレッドのIDを取得するには、廃止予定の AppDomain.GetCurrentThreadId
を使用できます。このメソッドは、Win32 APIメソッドGetCurrentThreadID
に対してPInvokeを使用し、WindowsのスレッドIDを返します。
.NET Threadオブジェクトは単一のWindowsスレッドに対応していないため、このメソッドは非推奨とマークされています。したがって、特定の.NETスレッドに対してWindowsから返される可能性のある安定したIDはありません。
これが事実であるより多くの理由のためにコンフィギュレータの答えを見てください。
OS IDを取得するには
AppDomain.GetCurrentThreadId()
MSDN によると、
非管理対象ホストが管理対象スレッドと非管理対象スレッド間の関係を制御できるため、オペレーティングシステムのThreadIdは管理対象スレッドと固定の関係にありません。特に、洗練されたホストはCLRホスティング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;
}
}
Windows 10でのオフセットは0x022C(x 64ビットアプリケーション)と0x0160(x 32ビットアプリケーション)です。
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
型には、基礎となるOS構造を指すDONT_USE_InternalThread
というプライベートIntPtrメンバフィールドが含まれています。ただし、これは実際には実装の詳細なので、このIMOを実行することはお勧めできません。そして名前の種類はあなたがこれに頼るべきでないことを示します。
System.Threading.Thread.CurrentThread.Name
System.Threading.Thread.CurrentThread.ManagedThreadId
マネージスレッドIDを返すThread.GetHashCodeを使用できます。もしあなたがGetHashCodeの目的を考えているなら、これは理にかなっています - それはオブジェクト(スレッド)のためのユニークな識別子(例えば辞書のキー)である必要があります。
Threadクラスの 参照ソース はここでは有益です。 (確かに、特定の.NET実装はこのソースコードに基づかないかもしれませんが、デバッグの目的で私は私のチャンスをつかむでしょう。)
GetHashCode は、「オブジェクトの等価性をすばやくチェックする必要があるアルゴリズムにこのハッシュコードを提供します」ので、スレッドの等価性をチェックするのに最適です。特定のメソッドが呼び出し元のスレッドで実行されていることを表明する。