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

时间:2018-09-16 23:14:17

标签: c++ windows multithreading winapi beginthreadex

我有一个线程,该线程创建一个隐藏的窗口,以便基于电源状态接收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更新。

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

我在这里想念什么?

1 个答案:

答案 0 :(得分: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函数。