简体   繁体   中英

C++11 Capture Member Variable in Lambda

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?

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.

You can only capture local variables, ie, 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, eg:

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM