-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.

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

我在这里想念什么?

4

1 回答 1

1

您的代码缺少必要的同步。你在这里是一场数据竞赛。因此,您得到的是严格未定义的行为。最有可能发生的是编译器不会hiddenWindowHandle在循环的每次迭代中从内存中重新获取 的值,因为它可以简单地假设该值不会改变。hiddenWindowHandle一种可能的解决方案是让std::atomic主线程执行繁忙的等待,直到值从NULL. 或者,您可以将对共享变量的所有访问权限放入由互斥锁锁定的临界区,或使用条件变量等待该值可用。

根据评论编辑:

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

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

这里有两个问题。首先,data不指向 a HWND,它指向 a std::atomic<HWND>now,所以你已经有未定义的行为。主要问题,也可能是为什么您的原始代码无论如何都不能正常工作的解释,尽管存在数据竞争,是您创建了一个新的本地HWND名为hwHandle. 这个局部变量被初始化为任何data指向的值。然后,您将结果分配给该局部变量,但永远不会分配给实际结果变量。

你想要做的是更多的事情

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

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

于 2018-09-16T23:44:16.183 回答