Поделиться через


Советы по отладке потоков

В этой статье содержатся полезные сведения об отладке потоков, включая сведения о настройке имен потоков для машинного и управляемого кода.

Советы по C/C++

Ниже приведены некоторые советы, которые можно использовать при отладке потоков в машинном коде:

  • Содержимое блока сведений о потоке можно просмотреть, введя @TIB в диалоговом окне "Просмотр " или в диалоговом окне "Быстрая проверка ".

  • Вы можете просмотреть последний код ошибки для текущего потока, введя @Err в окне "Наблюдение" или в диалоговом окне "Быстрый просмотр".

  • Функции библиотеки времени выполнения C (CRT) могут быть полезны для отладки многопоточного приложения. Дополнительные сведения см. в _malloc_dbg.

Установка имени для потока в C/C++

Именование потоков возможно в любом выпуске Visual Studio. Именование потоков полезно для идентификации потоков, интересующих окно Threads при отладке выполняющегося процесса. Наличие распознаваемых именованных потоков также может оказаться полезным при выполнении последующей отладки с помощью проверки аварийного дампа и при анализе записей производительности с помощью различных средств.

Способы задания имени потока

Существует два способа задать имя потока. Первое — через функцию SetThreadDescription . Во-вторых, создается определенное исключение при присоединении отладчика Visual Studio к процессу. Каждый подход имеет преимущества и предостережения. Использование SetThreadDescription поддерживается начиная с Windows 10 версии 1607 или Windows Server 2016.

Следует отметить, что оба подхода можно использовать вместе, если это необходимо, так как механизмы, с помощью которых они работают, не зависят друг от друга.

Задайте имя потока с помощью SetThreadDescription

Преимущества:

  • Имена потоков видны при отладке в Visual Studio независимо от того, был ли отладчик подключен к процессу во время вызова SetThreadDescription.
  • Имена потоков видны при отладке после смерти путем загрузки аварийного дампа в 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;
}

Назначение имени потока через генерацию исключения

Другой способ задать имя потока в программе — передать требуемое имя потока отладчику 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();
}