스레드에서 스레드 ID 얻기


319

예를 들어 C #에서 스레드를 디버깅 할 때 각 스레드의 ID를 볼 수 있습니다.

프로그래밍 방식으로 동일한 스레드를 얻는 방법을 찾을 수 없습니다. 현재 스레드의 ID를 (의 속성에서 Thread.currentThread) 가져올 수 없었습니다 .

따라서 Visual Studio에서 스레드의 ID를 얻는 방법이 궁금합니다. 2345예를 들어 id를 사용하여 스레드의 핸들을 얻는 방법이 있습니까?

답변:


437

GetThreadId주어진 네이티브 스레드의 ID를 반환합니다. 관리되는 스레드와 작동하게하는 방법이 있습니다. 스레드 핸들 만 찾아 해당 기능에 전달해야합니다.

GetCurrentThreadId 현재 스레드의 ID를 반환합니다.

GetCurrentThreadId.NET 2.0에서 더 이상 사용되지 않습니다. 권장되는 방법은 Thread.CurrentThread.ManagedThreadId속성입니다.


87
내가 이것을 발견하고 타이핑 한 다음 더 이상 사용되지 않는다고 들었으므로 현재 이것을 수행하는 방법은 Thread.CurrentThread.ManagedThreadId
James

3
ManagedThreadId는 앱에서 ManagedThreadId 속성 ID를 재사용 할 때 스레드를 식별하는 강력한 방법이 아닙니다. 따라서 일부 시나리오에서는 스레드의 신뢰할 수있는 식별자가 아니며 "같은 키를 가진 항목이 이미 추가되었습니다"라는 예외가 발생합니다. at line ... 스레드를 작성할 때 고유 한 이름을 지정하십시오.
Forer

15
이 게시물에는 매우 나쁜 조언이 있습니다. 몇몇 사람들은 "ManagedThreadId"를 사용하여 스레드를 식별 할 것을 권장합니다. 추천을 제거하기 위해 게시물을 편집했습니다. 몇 가지 지적한 것은 다른 유형의 스레드 ID가 있다는 것입니다. 관리되는 스레드 ID는 관리되지 않는 스레드 ID와 동일하지 않으며, 사람들이 해당 코드를 복사하여 붙여 넣으면 매우 미묘한 동기화 버그가 발생할 수 있습니다. Thread 클래스에 대한 MSDN의 설명서는 이것에 대해 매우 분명합니다. 수업 수준에서 의견을보십시오.
ShadowChaser

3
ID는 동기화하지 않지만 뮤텍스와 같은 동기화 프리미티브를 사용합니다. 이것은 디버깅 목적으로 만 사용됩니다.
Blindy

11
System.Threading.Thread.CurrentThread.ManagedThreadId에서 사용할 때 적어도 작동하지 않는 것을 알기 위해이 의견을 게시하고 싶습니다 SetWindowsHookEx. 대신 네이티브 win32 함수에서 스레드 ID를 가져와야합니다 GetCurrentThreadId().
King King

82

예를 들어 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와 스레드 사이의 관계가없는 것 같으므로 ID로 관리되는 스레드를 얻는 것은 어려운 일입니다.

관리 및 비 관리 스레딩에 대한 자세한 내용은 이 MSDN arcticle을 참조하십시오 .


4
다른 사람이 왜이 간단한 답을 찾지 못했습니까?
Stefan Steinegger

2
작동하지 않습니다. GetCurrentProcess (). Threads는 Thread로 변환 할 수없는 ProcessThreadCollection을 반환합니다. 쉬운 해결책이 없습니다.
mafu

2
@ mafutrct, 업데이트 된 답변. 이 속성은 실제로 .ProcessThreads라고합니다. 감사.
badbod99

2
두 개의 스레드 ID가 다른 것을 명확히하기 위해이 게시물을 다시 작성하도록 권장하십시오. 누군가가 마지막 문장을 읽지 못하면 ManagedThreadId를 연결하고 ProcessThread.Id에 매핑하여 동작을 만듭니다.
ShadowChaser

1
차이점을 강조하는 유용한 MSDN acticle에 대한 링크를 추가했습니다. 그러나 문제는 디버깅을위한 스레드 ID (이 경우 ManagedThreadID)를 얻는 것과 관련이 있습니다. OS와 관리되는 스레드의 차이점에 대한 세부 정보로 대답을 어수선하게 만드는 것은 유용하지 않다고 생각합니다.
badbod99

46

더 이상 사용되지 않는 AppDomain.GetCurrentThreadId것을 사용하여 현재 실행중인 스레드의 ID를 얻을 수 있습니다 . 이 메소드는 PInvoke를 Win32 API 메소드 GetCurrentThreadID로 사용하고 Windows 스레드 ID를 리턴합니다.

이 메서드는 .NET Thread 개체가 단일 Windows 스레드에 해당하지 않으므로 Windows에서 지정된 .NET 스레드에 대해 반환 할 수있는 안정적인 ID가 없기 때문에 더 이상 사용되지 않는 것으로 표시됩니다.

이것이 더 많은 이유에 대해서는 구성 자의 답변을 참조하십시오.


주의 .Net Core 2.2에서는 AppDomain.GetCurrentThreadId (MethodInfo를 통해 사용되지 않음으로 호출 됨)가 관리되는 스레드 ID (Process.GetCurrentProcess (). Threads와 일치하는 데는 쓸모 없음)를 반환합니다.
brewmanz

32

OS ID를 얻으려면 다음을 사용하십시오.

AppDomain.GetCurrentThreadId()

1
GetHashCode가 반드시 고유하지는 않습니다! 스레드를 식별하는 데 사용해서는 안됩니다.
Dror Helper

2
OS 스레드 ID를 원하는 경우 AppDomain.GetCurrentThreadId ()를 사용할 수 있지만 이론적으로 여러 .NET 스레드가 동일한 OS 스레드를 공유 할 수 있습니다. Thread.GetHashCode ()는 프로세스 전체에서 고유 한 값을 반환하도록 보장합니다.
Mark Byers

3
이 메소드는 더 이상 사용되지 않는 것으로 표시되며 적절한 이유가 있습니다. 더 큰 그림을 보려면 내 대답과 구성자를 참조하십시오.
Paul Turner

3
이것이 OS 스레드 ID를 얻는 유일한 방법입니다. 그리고 이것은 정답으로 표시되어야합니다. 그럼에도 불구하고 나는 더 이상 이것에 의존하지 않을 것입니다.
LolaRun 2009

1
AppDomain.GetCurrentThreadId()사용되지 않습니다 : AppDomain.GetCurrentThreadId 관리되는 스레드가 실행 중일 때 안정된 ID를 제공하지 않기 때문에 사용되지 않습니다 fibers (aka lightweight threads). 관리되는 스레드의 안정적인 식별자를 얻으려면 ManagedThreadIdon 속성을 사용하십시오 Thread. 사용법 :Thread.CurrentThread.ManagedThreadId
Lijo Joseph

22

MSDN 에 따르면 :

관리되지 않는 호스트는 관리되는 스레드와 관리되지 않는 스레드 간의 관계를 제어 할 수 있으므로 운영 체제 ThreadId는 관리되는 스레드와 고정 된 관계가 없습니다. 특히, 정교한 호스트는 CLR 호스팅 API를 사용하여 동일한 운영 체제 스레드에 대해 많은 관리되는 스레드를 예약하거나 다른 운영 체제 스레드간에 관리되는 스레드를 이동할 수 있습니다.

따라서 기본적으로 Thread객체는 반드시 OS 스레드와 일치하지 않아도되므로 기본 ID가 노출되지 않습니다.


VS2010의 디버그 / 스레드 창에 "관리 스레드 ID"가 표시됩니다. 이걸 어떻게 구할 수 있습니까?
Pavel Radzivilovsky

1
ManagedThreadID 속성 msdn.microsoft.com/en-us/library/…를 사용 하십시오 . 이것은 OS 스레드 ID와 동일하지 않습니다.
구성자

15

해킹하려는 사람들을 위해 :

    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;
    }

11

현재 쓰레드 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;
     }
}

OP가 관리되는 스레드 ID와 동일하지 않은 스레드의 OS ID를 요구한다고 생각합니다.
Brian Rasmussen

Process.Threads가의 컬렉션 반환 :이 코드는 작동하지 않습니다 ProcessThread이 동일하지 않습니다, 객체 (없으며 상속하지) Thread: (thread as Thread)널 참조를 반환합니다.
Fredrik Mörk

코드 코드에 몇 가지 버그가 있음을 발견했습니다. 지금 해결해보세요
Dror Helper

1
win32 id를 관리되는 스레드에 매핑하는 사전을 사용했습니다.
Contango

11

Windows 10에서 오프셋은 0x022C (x64 비트 응용 프로그램) 및 0x0160 (x32 비트 응용 프로그램)입니다.

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;
}

1
Windows 7 x64 SP1에서도 작동합니다. 그러나 권장하지 않습니다. 임시 테스트에서만 사용하십시오.
guan boshen

5

시스템. 스레딩. 스레드. 현재 스레드 이름

System.Threading.Thread.CurrentThread.ManagedThreadId

5

관리 코드 Thread에서 각 관리 스레드 유형의 인스턴스에 액세스 할 수 있습니다 . ThreadOS 스레드의 개념을 캡슐화하고 현재 CLR에서 관리되는 스레드 및 OS 스레드와 일대일로 대응합니다. 그러나 이것은 구현 세부 사항이며 향후 변경 될 수 있습니다.

Visual Studio에 표시되는 ID는 실제로 OS 스레드 ID입니다. 이다 없는 몇 가지 응답에 의해 제안 관리되는 스레드 ID와 동일.

Thread유형에는 DONT_USE_InternalThread기본 OS 구조를 가리키는 개인 IntPtr 구성원 필드가 포함됩니다 . 그러나 이것은 실제로 구현 세부 사항이므로이 IMO를 추구하는 것은 좋지 않습니다. 그리고 일종의 이름은 당신이 이것에 의존해서는 안된다는 것을 나타냅니다.


GetThreadId를 사용하려면 DONT_USE 필드에서 얻는 핸들이 필요합니다.
구성자

나는 알고 있지만 실제로 관리 된 스레드가 OS 스레드에 직접 매핑된다는 사실을 믿을 수는 없으므로 믿을 수는 없습니다.
Brian Rasmussen

설명을 해주셔서 감사합니다. 문제를 요약하십시오. 그러나 이제 여러 관리 스레드가 단일 OS 스레드에 해당 할 수 있다면 (구성자가 말했듯이 감사합니다) VS는 관리 스레드가 아닌 OS 스레드를 표시합니다.
LolaRun 2009

@OhrmaZd : 예, VS2005 / 2008은 스레드 창에 관리 스레드에 대한 OS ID를 표시합니다. VS2010B2는 실제로 스레드 당 OS와 관리 ID를 모두 표시합니다.
Brian Rasmussen

@Brian Rasmussen : 이제 관리되는 스레드의 식별입니다! 지식을 공유해 주셔서 감사합니다.
LolaRun 2009

4

관리되는 스레드 ID를 반환하는 Thread.GetHashCode를 사용할 수 있습니다. GetHashCode의 목적에 대해 생각할 경우 이는 의미가 있습니다. 객체 (스레드)의 고유 식별자 (예 : 사전의 키) 여야합니다.

Thread 클래스참조 소스 는 여기에 도움이됩니다. (특정 .NET 구현 이 소스 코드를 기반으로하지 않을 수도 있지만 디버깅 목적으로 기회를 잡을 것입니다.)

GetHashCode는 "개체 동등성을 빠르게 검사해야하는 알고리즘에이 해시 코드를 제공합니다."따라서 스레드 동등성을 검사하는 데 적합합니다.


4
놀랍게도, 나는이 5 살짜리 질문을 한 시간 동안 열었고, 돌아와서 "이 질문에 대한 1 개의 새로운 답변"을 보았습니다. : D
Ray

이 답변은 다른 의견에서 암시되었지만 나중에 추가 조사를 한 결과 사용되었습니다. OP가 원하는 것이 아닐 수도 있습니다. 아마도 OP는 더 이상 신경 쓰지 않을 것입니다. 다른 사람에게 유용 할 수 있습니다. (적어도 참조 소스를 기준으로 스레드 ID를 얻는 가장 효율적인 방법 일 수 있습니다.)
yoyo

글쎄, 나는 지금 다른 분야에 있지만, 그때 우리는 스레드에 대한 두 개의 ID, 기본 스레드의 ID 및 관리되는 스레드의 ID를 가지고 있었고 하나는 다른 하나에 속한다. ID는 스레드를 식별하기위한 것이며 GetHashCode에는 다른 유틸리티가 있으며 충돌 할 수 있습니다. 우리가 GetHashCode 사용했다 경우 프레임 워크 개발자는 ID를 구현하지 않았을
LolaRun

3
@yoyo 충돌은 사전 사용을 중단하지 않습니다. 충돌 가능성이 낮고 전혀 충돌하지 않도록 설계되었습니다. 128 비트 값을 64 비트 값으로 해시하면 모든 해시 값에는 약 2 ^ 64 개의 충돌이 발생합니다. 사전은 드물게 충돌이 발생할 때 폴백 알고리즘 을 갖도록 설계되었습니다 .
bradgonesurfing

2
@bradgonesurfing 당신은 절대적으로 옳고, 나의 이전 의견은 잘못되었습니다. 해시 충돌로 인해 사전 성능이 저하되지만 기능은 올바르게 유지됩니다. 오해의 소지가있는 점에 대해 사과드립니다. 지적 해 주셔서 감사합니다.
yoyo 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.