Reputation: 23525
I have a member variable defined as:
HWND WindowHandle.
I'm trying to capture the variable and assign to it in the Lambda. So the compiler gave me a warning and suggested that I capture "this". I did, but now the Handle is only valid within the Lambda :S Inother words, it is NULL outside of the Lambda.
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.
}
The above creates the window perfectly fine! It's just the Handle is null. How can I get the Handle from within the Lambda to my class Member?
Upvotes: 3
Views: 1317
Reputation: 154045
You can only capture local variables, i.e., something declared in the function where the lambda is created or one of its argument. In a member function when accessing a member x
you are actually accessing this->x
with this
being the implicit pointer to the object passed to the member function. The lambda would, thus, capture this
rather than x
. To capture a member you'll need to create a local variable holding it and then capture this variable, e.g.:
auto&& tmpWindowHandle = this->WindowHandle; // ... or just WindowHandle
... and then you'd capture tmpWindowHandle
in your lambda function.
Since your lambda function doesn't show any synchronization it seems that your GetWindowHandle()
also doesn't have any synchronization and your calling thread probably access the WindowHandle
member before you it is set by the thread: You'll need some form of synchronization, be it a join()
or some form of mutexex or condition variables before you can call use the WindowHandle
from some other thread. The overall setup looks like a good application of a std::future<...>
: It is intended to run a function potentially concurrently and then block until the result is necessary when the result is actually accessed.
Upvotes: 0
Reputation: 11977
You are assigning the WindowHandle
on different thread. So what probably happens is that your new thread has not yet started and you are checking if WindowHandle
has changed already. Also, you should protect access to WindowHandle
with some mutex or other construct, otherwise you will have a race condition.
Upvotes: 0
Reputation: 51920
That's because your code has a race condition. By the time you check the value in main(), the thread has not run yet, so WindowHandle is still NULL.
Unless you didn't actually start the thread yet. In that case, since the thread hasn't executed, WindowHandle is still NULL.
In any event, you need to synchronize access to WindowHandle between threads with a mutex.
Upvotes: 5