次の方法で共有


スレッドのデバッグに関するヒント

この記事では、ネイティブ コードとマネージド コードのスレッド名の設定に関する情報など、スレッドのデバッグに役立つ情報を提供します。

C/C++ のヒント

ネイティブ コードでスレッドをデバッグするときに使用できるヒントを次に示します。

  • スレッド情報ブロックの内容を表示するには、[@TIB] ウィンドウまたは [クイック ウォッチ] ダイアログ ボックスに「」と入力します。

  • [@Err] ウィンドウまたは [クイック ウォッチ] ダイアログ ボックスに「」と入力すると、現在のスレッドの最後のエラー コードを表示できます。

  • C Run-Time ライブラリ (CRT) 関数は、マルチスレッド アプリケーションのデバッグに役立ちます。 詳細については、 _malloc_dbgを参照してください。

C/C++ でスレッド名を設定する

スレッドの名前付けは、Visual Studio のどのエディションでも可能です。 スレッドの名前付けは、実行中のプロセスをデバッグするときに、[スレッド] ウィンドウで目的の スレッド を識別するのに役立ちます。 また、クラッシュ ダンプ検査を使用して事後デバッグを実行する場合や、さまざまなツールを使用してパフォーマンス キャプチャを分析する場合にも、スレッドに名前を付けると便利です。

スレッド名を設定する方法

スレッド名を設定するには、2 つの方法があります。 1 つ目は SetThreadDescription 関数を使用することです。 2 つ目は、Visual Studio デバッガーがプロセスにアタッチされている間に特定の例外をスローすることです。 各アプローチには利点と注意事項があります。 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 でクラッシュが作成された場合にのみ、スレッド名が表示されます。

Example:

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

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

    return 0;
}

例外をスローしてスレッド名を設定する

プログラムでスレッド名を設定するもう 1 つの方法は、特別に構成された例外をスローして、目的のスレッド名を 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();
}