【问题标题】:C++: _beginthreadex, thread function name not showing in Visual Studio Threads windowC++:_beginthreadex,线程函数名称未显示在 Visual Studio 线程窗口中
【发布时间】:2011-08-18 17:06:22
【问题描述】:

我最近了解到::_beginthreadex() 总是比::CreateThread() 更可取,因此我更改了所有使用::CreateThread() 的调用。

唯一的缺点是我不再在 Visual Studio 的 Threads 窗口中看到线程函数的名称,这使得快速识别线程变得很困难。我假设这是在我使用::CreateThread() 时由调试器自动完成的,因为参数完全相同,我只是更改了所用函数的名称。

有什么方法可以继续使用::_beginthreadex(),并在Visual Studio 的Threads 窗口中查看线程名称?

【问题讨论】:

    标签: c++ visual-studio multithreading visual-studio-2010 beginthreadex


    【解决方案1】:

    这是因为_beginthreadex() 调用CreateThread() 使用自己的线程函数调用您指定的函数(因此调试器使用_threadstartex 函数名称-_beginthreadex() 调用的函数名称)。

    您可以使用 MSDN 中的 SetThreadName() 示例自己手动设置线程名称。您可能想要做的是为_beginthreadex() 创建自己的包装器,可能看起来像:

    uintptr_t startthreadex(
        void* security, 
        unsigned stacksize, 
        unsigned (__stdcall * threadproc) (void *), 
        void* args, 
        unsigned flags, 
        unsigned * pThread_id,
        char* thread_name)
    {
        unsigned alt_thread_id;
    
        if (!pThread_id) {
            pThread_id = & alt_thread_id;
        }
    
        uintptr_t result = _beginthreadex(security, stacksize, threadproc, args, flgas, pThread_id);
    
        if (result == 0) return result;
    
        SetThreadName( *pThread_id, thread_name);
    }
    

    现在您可以调用 startthreadex() 而不是 _beginthreadex() 并传递线程名称。这样做的一个小优点是,如果您使用相同的函数来运行多个线程,您可以轻松地为它们赋予每个唯一的名称,以反映传递给线程或其他任何参数的参数。

    如果您希望线程名称自动将线程 proc 函数名称作为调试器的线程名称,您可以制作一个包装宏,将函数名称参数字符串化(它所需要的只是另一个级别的间接或解决任何问题...)。

    这里是SetThreadName()(来自http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx):

    //
    // Usage: SetThreadName (-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, char* threadName)
    {
       THREADNAME_INFO info;
       info.dwType = 0x1000;
       info.szName = threadName;
       info.dwThreadID = dwThreadID;
       info.dwFlags = 0;
    
       __try
       {
          RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
       }
       __except(EXCEPTION_EXECUTE_HANDLER)
       {
       }
    }
    

    【讨论】:

      【解决方案2】:

      【讨论】:

      • 对不起,您提供的所有链接都提倡使用_beginthreadex。他们说它不太容易出现内存泄漏,这在我的应用程序中非常重要,它是广泛多线程的
      • 在今天的编译器/链接器和库中,_beginthreadex 没有带来额外的优势。别说VC6,已经很过时了。
      • 我的代码虽然很少会与 VC6 二进制文件交互,所以我宁愿安全行事
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-20
      • 2015-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多