3

我有一个成员变量定义为:

HWND 窗口句柄。

我正在尝试捕获变量并在 Lambda 中分配给它。所以编译器给了我一个警告并建议我捕获“this”。我做到了,但现在句柄只在 Lambda 中有效:S 换句话说,它在 Lambda 之外是 NULL。

class Foo
{
    private:
        HWND WindowHandle;

    public:
        Foo();
        void MakeWindow(.......);
        HWND GetWindowHandle() {return WindowHandle;};
};

Foo::Foo(){}

Foo::MakeWindow(.......)
{
    Thread = std::thread([ClassName, Title, Width, Height, this]{
                    WindowHandle = CreateWindowEx(0, ClassName.c_str(), Title.c_str(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, Width, Height, 0, 0, GetModuleHandle(NULL), 0);
                    if(WindowHandle)
                    {
                        ShowWindow(WindowHandle, SW_SHOWDEFAULT);
                        MSG msg;
                        while(GetMessage(&msg, 0, 0, 0))
                            DispatchMessage(&msg);
                    }
                });
}


int main()
{
    Foo F;
    F.MakeWindow(........);
    std::cout<<std::boolalpha<<(F.GetWindowHandle() == NULL);  //writes true.
}

以上创建的窗口非常好!只是句柄为空。如何从 Lambda 中获取句柄给我的班级成员?

4

3 回答 3

5

那是因为您的代码具有竞争条件。当您检查 main() 中的值时,线程尚未运行,因此 WindowHandle 仍然为 NULL。

除非你还没有真正启动线程。在这种情况下,由于线程尚未执行,WindowHandle 仍然为 NULL。

无论如何,您需要使用互斥锁在线程之间同步对 WindowHandle 的访问。

于 2012-12-25T15:44:19.550 回答
0

您只能捕获局部变量,即在创建 lambda 的函数中声明的内容或其参数之一。在成员函数中,当访问一个成员时,x您实际上是通过作为传递给成员函数的对象的隐式指针来访问this->x的。this因此,lambda 将捕获this而不是x. 要捕获成员,您需要创建一个保存它的局部变量,然后捕获该变量,例如:

auto&& tmpWindowHandle = this->WindowHandle; // ... or just WindowHandle

...然后你会tmpWindowHandle在你的 lambda 函数中捕获。

由于您的 lambda 函数没有显示任何同步,因此您似乎GetWindowHandle()也没有任何同步,并且您的调用线程可能会WindowHandle在您被线程设置之前访问该成员:您将需要某种形式的同步,无论是join()或某种形式的互斥锁或条件变量,然后您可以WindowHandle从其他线程调用使用。整体设置看起来像是 a 的一个很好的应用std::future<...>:它旨在潜在地同时运行一个函数,然后阻塞,直到实际访问结果时需要结果。

于 2012-12-25T15:44:48.910 回答
0

您正在分配WindowHandle不同的线程。所以可能发生的是你的新线程还没有开始,你正在检查是否WindowHandle已经改变。此外,您应该使用一些互斥锁或其他构造来保护访问WindowHandle,否则您将遇到竞争条件。

于 2012-12-25T15:45:37.397 回答