为什么beginthreadex线程参数变量不在父线程中更新

问题描述 投票:-1回答:1

我有一个线程,它创建一个隐藏的窗口,以便根据电源状态接收WinAPI消息。我需要从线程中获取创建窗口的HWND,以便我可以抛出WM_QUIT消息来关闭窗口并优雅地结束线程:

主要:

HWND hiddenWindowHandle = NULL;
HANDLE PowerWindowThreadHandle = (HANDLE)_beginthreadex(0, 0, &windowsPowerThread, (void*)&hiddenWindowHandle, 0, 0);

线:

unsigned int __stdcall windowsPowerThread(void* data)
{
    HWND hiddenWindowHandle = createHiddenWindow();
    HWND hwHandle = *(HWND*)data;
    hwHandle = hiddenWindowHandle;
    ...

问题是hiddenWindowHandle没有使用生成的HWND进行更新。

我已经在线程中验证了它正在创建,并且我已经验证我在线程创建之前我没有尝试访问句柄。

我在这里错过了什么?

c++ windows multithreading winapi beginthreadex
1个回答
1
投票

您的代码缺乏必要的同步。你在这里有一个data race。因此,你得到的是严格未定义的行为。最有可能发生的是编译器在循环的每次迭代中都不会从内存中重新获取hiddenWindowHandle的值,因为它可以简单地假设值不会改变。一种可能的解决方案是使hiddenWindowHandle成为std::atomic并让主线程执行忙等待,直到值从NULL变化。或者,您可以将共享变量的所有访问权限放入由mutex锁定的关键部分,或使用condition variable等待值可用。

根据评论进行编辑:

因此,如果我正确理解您的代码,创建窗口的线程会以void*的形式接收指向结果变量的指针,然后尝试传达结果,如下所示:

unsigned int __stdcall windowsPowerThread(void* data)
{
    …
    HWND hwHandle = *(HWND*)data;
    hwHandle = hiddenWindowHandle;
    …
}

这里有两个问题。首先,data没有指向HWND,它现在指向std::atomic<HWND>,所以你已经在那里有未定义的行为。主要问题,也可能解释为什么你的原始代码不会恰好相反,尽管数据竞争,是你创建一个新的本地HWND称为hwHandle。这个局部变量用data指向的值初始化。然后,将结果分配给该局部变量,但从不分配给实际的结果变量。

你想要做的是更多的东西

unsigned int __stdcall windowsPowerThread(void* data)
{
    …
    HWND hiddenWindowHandle = createHiddenWindow(…);
    *static_cast<std::atomic<HWND>*>(data) = hiddenWindowHandle;
    …
}

您可能还想考虑使用std::thread而不是原始CRT函数。

© www.soinside.com 2019 - 2024. All rights reserved.