我有一个成员变量定义为:
HWND WindowHandle。
我正在尝试捕获变量并在Lambda中分配它。所以编译器给了我一个警告,并建议我捕获“这个”。我做了,但现在Handle只在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.
}
以上创建窗口完美!它只是Handle为null。如何从Lambda中获取Handle到我的班级成员?
答案 0 :(得分:5)
那是因为你的代码有竞争条件。当你检查main()中的值时,线程还没有运行,所以WindowHandle仍然是NULL。
除非你实际上没有启动线程。在这种情况下,由于线程尚未执行,因此WindowHandle仍为NULL。
无论如何,您需要在具有互斥锁的线程之间同步对WindowHandle的访问。
答案 1 :(得分:0)
您只能捕获局部变量,即在创建lambda的函数中声明的内容或其参数之一。在访问成员x
时的成员函数中,您实际访问this->x
,this
是传递给成员函数的对象的隐式指针。因此,lambda将捕获this
而不是x
。要捕获成员,您需要创建一个包含它的局部变量,然后捕获此变量,例如:
auto&& tmpWindowHandle = this->WindowHandle; // ... or just WindowHandle
...然后你将在lambda函数中捕获tmpWindowHandle
。
由于你的lambda函数没有显示任何同步,你的GetWindowHandle()
似乎也没有任何同步,你的调用线程可能会在你被线程设置之前访问WindowHandle
成员:在调用其他线程使用join()
之前,您需要某种形式的同步,无论是WindowHandle
还是某种形式的互斥或条件变量。整体设置看起来像std::future<...>
的良好应用:它旨在可能同时运行一个函数然后阻塞,直到实际访问结果时需要结果。
答案 2 :(得分:0)
您正在不同的主题上分配WindowHandle
。所以可能发生的事情是你的新线程还没有开始,你正在检查WindowHandle
是否已经改变了。此外,您应该使用某些互斥锁或其他构造来保护对WindowHandle
的访问,否则您将遇到竞争条件。