다음을 통해 공유


스레드 디버깅을 위한 팁

이 문서에서는 네이티브 및 관리 코드의 스레드 이름 설정에 대한 정보를 비롯하여 스레드 디버깅에 유용한 정보를 제공합니다.

C/C++ 팁

다음은 네이티브 코드에서 스레드를 디버깅할 때 사용할 수 있는 몇 가지 팁입니다.

  • 조사식 창이나 간략한 조사식 대화 상자에 @TIB를 입력하면 스레드 정보 블록의 내용이 표시됩니다.

  • 조사식 창이나 간략한 조사식 대화 상자에 @Err을 입력하면 현재 스레드의 마지막 오류 코드가 표시됩니다.

  • CRT(C Run-Time Libraries) 함수는 다중 스레드 애플리케이션을 디버깅하는 데 유용합니다. 자세한 내용은 _malloc_dbg를 참조하세요.

C/C++에서 스레드 이름 설정

스레드 명명 기능은 Visual Studio의 모든 버전에서 사용할 수 있습니다. 스레드 이름 지정은 실행 중인 프로세스를 디버그할 때 스레드 창에서 원하는 스레드를 식별하는 데 유용합니다. 쉽게 알 수 있는 이름이 지정된 스레드를 포함하는 것은 크래시 덤프 검사를 통해 사후 평가 디버깅을 수행할 경우 및 다양한 도구를 사용하여 성능 캡처를 분석할 경우 유용할 수 있습니다.

스레드 이름을 설정하는 방법

스레드 이름을 설정하는 방법에는 두 가지가 있습니다. 첫 번째는 SetThreadDescription 함수를 사용하는 것입니다. 두 번째는 Visual Studio 디버거가 프로세스에 연결되는 동안 특정 예외를 throw하는 것입니다. 각 접근 방식에는 이점과 주의 사항이 있습니다. SetThreadDescription 사용은 Windows 10 버전 1607 또는 Windows Server 2016부터 지원됩니다.

접근 방식의 작동 메커니즘은 서로 독립적이므로 접근 방식을 둘 다 함께 사용할 수 있습니다.

SetThreadDescription을 사용하여 스레드 이름 설정

혜택:

  • SetThreadDescription이 호출될 때 디버거가 프로세스에 연결되었는지 여부와 관계없이 Visual Studio에서 디버그할 때 스레드 이름이 표시됩니다.
  • Visual Studio에서 크래시 덤프를 로드하여 사후 평가 디버깅을 수행할 때 스레드 이름이 표시됩니다.
  • WinDbg 디버거 및 Windows Performance Analyzer 성능 분석기와 같은 다른 도구를 사용하는 경우에도 스레드 이름이 표시됩니다.

주의 사항:

  • 스레드 이름은 Visual Studio 2017 버전 15.6 이상 버전에서만 표시됩니다.
  • 사후 평가에서 크래시 덤프 파일을 디버그할 때 Windows 10 버전 1607, Windows Server 2016 이상 버전의 Windows에서 크래시가 생성된 경우에만 스레드 이름이 표시됩니다.

예시:

#include <windows.h>
#include <processthreadsapi.h>

int main()
{
    HRESULT r;
    r = SetThreadDescription(
        GetCurrentThread(),
        L"ThisIsMyThreadName!"
    );

    return 0;
}

예외를 throw하여 스레드 이름 설정

프로그램에서 스레드 이름을 설정하는 또 다른 방법은 특별 구성된 예외를 throw하여 원하는 스레드 이름을 Visual Studio 디버거에 전달하는 것입니다.

혜택:

  • 모든 버전의 Visual Studio에서 작동합니다.

주의 사항:

  • 예외 기반 메서드가 사용될 때 디버거가 연결되는 경우에만 작동합니다.
  • 이 방법을 사용하여 설정된 스레드 이름은 덤프 또는 성능 분석 도구에서 사용할 수 없습니다.

예시:

아래 표시된 SetThreadName 함수는 이 예외 기반 접근 방식을 보여 줍니다. threadName 호출이 완료된 후 SetThreadName 매개 변수의 메모리가 해제될 수 있도록 스레드 이름은 자동으로 스레드에 복사됩니다.

//
// Usage: SetThreadName ((DWORD)-1, "MainThread");
//
#include <windows.h>
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
    DWORD dwType; // Must be 0x1000.
    LPCSTR szName; // Pointer to name (in user addr space).
    DWORD dwThreadID; // Thread ID (-1=caller thread).
    DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void SetThreadName(DWORD dwThreadID, const char* threadName) {
    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = threadName;
    info.dwThreadID = dwThreadID;
    info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable: 6320 6322)
    __try{
        RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
    }
    __except (EXCEPTION_EXECUTE_HANDLER){
    }
#pragma warning(pop)
}

관리 코드에 스레드 이름 설정

스레드 명명 기능은 Visual Studio의 모든 버전에서 사용할 수 있습니다. 이 기능은 스레드 창에서 스레드를 추적할 때 유용합니다.

관리 코드에 스레드 이름을 설정하려면 Name 속성을 사용합니다.

예시

public class Needle
{
    // This method will be called when the thread is started.
    public void Baz()
    {
        Console.WriteLine("Needle Baz is running on another thread");
    }
}

public void Main()
{
    Console.WriteLine("Thread Simple Sample");
    Needle oNeedle = new Needle();
    // Create a Thread object.
    System.Threading.Thread oThread = new System.Threading.Thread(oNeedle.Baz);
    // Set the Thread name to "MyThread".
    oThread.Name = "MyThread";
    // Starting the thread invokes the ThreadStart delegate
    oThread.Start();
}