다음을 통해 공유


스레드 디버깅 팁

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

C/C++ 팁

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

  • @TIB을(를) 조사식 창이나 빠른 조사식 대화 상자에 입력하여 스레드 정보 블록의 내용을 볼 수 있습니다.

  • Watch 창이나 빠른 조사식 대화 상자에 @Err를 입력하여 현재 스레드의 마지막 오류 코드를 볼 수 있습니다.

  • CRT(C Run-Time 라이브러리) 함수는 다중 스레드 애플리케이션을 디버깅하는 데 유용할 수 있습니다. 자세한 내용은 _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 성능 분석기 성능 분석기와 같은 다른 도구를 사용할 때 스레드 이름도 표시됩니다.

주의 사항:

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

Example:

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

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

    return 0;
}

스레드 이름을 설정하고 예외를 발생시킴

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

혜택:

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

주의 사항:

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

Example:

아래에 표시된 함수는 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 .

Example

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