c++ 从std::thread::id结构中检索Windows线程标识符

frebpwbc  于 2022-12-20  发布在  Windows
关注(0)|答案(3)|浏览(127)

我可以在代码中访问std::thread::id,并且需要使用一些本机函数,这些函数将ThreadId作为DWORD的参数接收(与GetCurrentThreadId()返回的相同)。
我找不到从std::thread::id转换到Win32 DWORD ThreadId的任何方法。我能找到的最接近的东西是std::thread具有native_handle。但是我仍然没有办法创建std::thread来从std::thread::id获得native_handle,所以我仍然离我需要的太远了。
是不是我遗漏了什么?或者是标准的可移植线程函数和本地函数之间差距太大了,以至于标准的API无法满足我的需求?

syqv5f0l

syqv5f0l1#

这个答案将假设您使用的是MSVC 2015中的微软std::thread示例,并且有关它的记录事实在未来不会改变。
在文档下没有办法从std::thread::id转到native_handle
您可以尝试维护一个从std::thread::idstd::threadnative_handle的表,但实际上需要一个瓶颈,您可以控制所有std::thread的创建,这似乎有点多。
如果你测试std::thread::id整数的值,你会发现它和本机句柄在当前时间 * 的位数是一样的,所以你可以从事相当可怕的未定义的行为,提取位数并转换成整数,这样做是不建议的,因为你相信微软从来没有改变它的实现的非文档化细节;这是一个等待发生的bug和维护噩梦。
因此,尝试用不同的方法来解决你的问题。直接请求native_handle,或者不用原生API来解决你的问题。在很多情况下,使用原生API是一个坏兆头;这种用法有一半涉及到试图从线程外部挂起或终止线程,这在C++中是一个非常非常糟糕的主意(一般来说,确实如此)。

83qze16e

83qze16e2#

下面是从std::thread::id获取内部线程id表示rtl实现特定方法,请参见here

// 
#include <iostream>
#include <thread>

#ifdef _WIN32
#include <Windows.h>
#endif

namespace ns
{
    struct dummy{};
    using thread_id_access=std::basic_ostream<dummy>;
}

namespace std
{
    template <>
    class basic_ostream<ns::dummy>
    {
    public:
#if defined(_WIN32)
        using id_type=unsigned int;
#elif defined(_GLIBCXX_RELEASE)         
        using id_type=std::thread::native_handle_type;
#else
    #error Consult your rtl implementation
#endif            
        id_type id=0;
    };
    
    template<>
    ns::thread_id_access & operator <<(ns::thread_id_access & os, std::thread::id id) 
    {
#if defined(_GLIBCXX_RELEASE)         
        os.id=id._M_thread;
#elif defined(_MSC_VER)        
        os.id=id._Id;
#else
    #error Consult your rtl implementation        
#endif        
        return os;
    }
}

namespace ns
{
    inline auto GetThreadId(std::thread::id id)
    {
        thread_id_access t;
        t<<id;
        return t.id;    
    }
}

int main() 
{
    auto const id=std::this_thread::get_id();
    std::cout<<std::hex<<id<<"\n";
    std::cout<<std::hex<<ns::GetThreadId(id)<<"\n";
 #ifdef _WIN32   
    std::cout<<GetCurrentThreadId()<<"\n";
#endif    
    return 0;
}
k7fdbhmy

k7fdbhmy3#

至少在Visual C++中,您可以轻松获取Windows线程标识符。std::thread::native_handle()返回Win32线程句柄,Win32 API函数GetThreadId()返回线程标识符:

#include <thread>

void stopGUIThread(std::thread& guiThread)
{
    if (guiThread.joinable())
    {
        auto threadId = ::GetThreadId(guiThread.native_handle());
        assert(threadId != 0);
        // PostThreadMessage() will return 0 if the thread has
        // already finished its execution.
        ::PostThreadMessage(threadId, WM_QUIT, 0, 0);
        guiThread.join();
    }
}

相关问题