Definir um nome de thread em código nativo

A nomeação de thread é possível em qualquer edição do Visual Studio. A nomenclatura de thread é útil para identificar threads de interesse na janela Threads ao depurar um processo em execução. Ter threads com nomes reconhecíveis também pode ser útil ao executar a depuração pós-morte por meio da inspeção de despejo de memória e ao analisar capturas de desempenho usando várias ferramentas.

Maneiras de definir um nome de thread

Há duas maneiras de definir um nome de thread. A primeira é por meio da função SetThreadDescription. A segunda é gerando uma exceção específica enquanto o depurador do Visual Studio está anexado ao processo. Cada abordagem possui benefícios e desvantagens. O uso de SetThreadDescription tem suporte a partir do Windows 10, versão 1607 ou Windows Server 2016.

Vale a pena observar que ambas as abordagens podem ser usadas juntas, se desejar, pois os mecanismos por meio dos quais elas funcionam são independentes uns dos outros.

Definir um nome de thread usando SetThreadDescription

Benefícios:

  • Os nomes de thread ficam visíveis durante a depuração no Visual Studio, independentemente de o depurador ter sido anexado ou não ao processo no momento em que SetThreadDescription é invocado.
  • Os nomes de thread ficam visíveis ao executar a depuração pós-morte carregando um despejo de memória no Visual Studio.
  • Os nomes de thread também são visíveis ao usar outras ferramentas, como o depurador WinDbg e o analisador de desempenho do Windows Performance Analyzer.

Restrições:

  • Os nomes de thread só são visíveis no Visual Studio 2017 versão 15.6 e versões posteriores.
  • Ao depurar um arquivo de despejo de memória pós-morte, os nomes de thread só ficarão visíveis se a falha tiver sido criada no Windows 10 versão 1607, Windows Server 2016 ou versões posteriores do Windows.

Exemplo:

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

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

    return 0;
}

Definir um nome de thread lançando uma exceção

Outra maneira de definir um nome de thread em seu programa é comunicar o nome do thread desejado para o depurador do Visual Studio lançando uma exceção especialmente configurada.

Benefícios:

  • Funciona em todas as versões do Visual Studio.

Restrições:

  • Só funcionará se o depurador estiver anexado no momento em que o método baseado em exceção for usado.
  • Os nomes de thread definidos usando esse método não estarão disponíveis em despejos ou ferramentas de análise de desempenho.

Exemplo:

A função SetThreadName mostrada abaixo demonstra essa abordagem baseada em exceção. Observe que o nome do thread será copiado automaticamente para o thread, para que a memória do parâmetro threadName possa ser liberada após a conclusão da chamada 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)
}