65.9K
CodeProject 正在变化。 阅读更多。
Home

当前线程句柄

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2022年12月27日

MIT

1分钟阅读

viewsIcon

16627

当你想要使用当前线程句柄时该怎么做

引言

当你需要获取当前线程的句柄时,可以使用 GetCurrentThread,它会给你一个伪句柄,你不需要关闭它,因为它不是一个真正的引用计数句柄。文档中对此有明确说明。然而,我最近就遇到了这个问题。我想分享一下,以便其他人可以避免追查这个问题。

我的困惑

考虑以下示例

DWORD worker(void* ctx)
{
    std::cout << "Thread id: " << GetThreadId((HANDLE)ctx) << std::endl;
    return 0;
}

int main()
{
    HANDLE hMainThread = GetCurrentThread();
    std::cout << "Thread id: " << GetThreadId(hMainThread) << std::endl;

    HANDLE hThread = CreateThread(NULL, 0, worker, hMainThread, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);    
}

事情是这样的

我没有仔细思考,就假设这个伪句柄只是实际句柄的一个弱引用(当前句柄的一个非引用计数副本),并且可以在工作线程中引用它。但实际上,它是一个特殊的常量,字面意思是“当提供此句柄值时,使用当前线程”。如果你将该特殊值传递到另一个线程,那么该值将转换为“那个”线程的线程句柄。

如果你阅读文档,它会明确说明这一点。只是我没有停下来思考这到底意味着什么。

获取真正的线程句柄

如果你想获取一个可以传递到另一个线程的真实句柄,请这样做

    HANDLE hMainThread = NULL;
    if (!DuplicateHandle(
        GetCurrentProcess(),
        GetCurrentThread(),
        GetCurrentProcess(),
        &hMainThread,
        0,
        FALSE,
        DUPLICATE_SAME_ACCESS)) {
        cout << "Error " << GetLastError() << " cannot duplicate main handle." << endl;
        return GetLastError();
    }

当然,当你这样做时,你会得到一个 HANDLE 值,当你不再需要它时,你需要关闭它。

关注点

正如我所说,这没什么了不起的,文档也解释了这一点。但是,我花了一段时间才明白为什么我的 APC 被调度到错误的线程,也许我可以为其他人省去麻烦。:)

历史

  • 2022年12月27日:初稿
© . All rights reserved.