Question

Inside my app, I want to send a message to a dialog from a different thread. I want to pass an std::exception derived class reference to the dialog.

Something like this:

try {
       //do stuff
}
catch (MyException& the_exception) {
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, 0); //send the_exception or the_exception.error_string() here
}

I want to receive the message in my dialog and show the error that is in the_exception.error_string()

LPARAM CMyDlg::SomeError(WPARAM, LPARAM)
{
    show_error( ?????
    return 0;
}

passing the std::string the_exception.error_string() using PostMessage would also be ok, I guess.

Was it helpful?

Solution

You can't pass the address of the string in PostMessage, since the string is probably thread-local on the stack. By the time the other thread picks it up, it could have been destroyed.

Instead, you should create a new string or exception object via new and pass its address to the other thread (via the WPARAM or LPARAM parameter in PostMessage.) The other thread then owns the object and is responsible for destroying it.

Here is some sample code that shows how this could be done:

try
{
    //do stuff
}
catch (MyException& the_exception)
{
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, new string(the_exception.error_string));
}


LPARAM CMyDlg::SomeError(WPARAM, LPARAM lParam)
{
    // Put in shared_ptr so it is automatically destroyed.
    shared_ptr<string> msg = reinterpret_cast<string*>(lParam);

    // Do stuff with message

    return 0;
}

OTHER TIPS

As long as you are within a process simply passing a void* pointer and some care on object lifetime are enough.

If is SendMessage you can pass it in LPARAM as a void* cast, and the client uncast it back to your string type. Because SendMessage is synchronous, you are safe:

If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message

If you want to use PostMessage then you'll have to do an explicit hand off because the call is asynchronous: make a copy of the string on the heap and by calling the PostMessage you have passed the delete responsability to the calee (the dialog).

If you go out of process (MyhWnd belongs to a different process) then is a whole different story and you'll have to marshal your message into something like a global atom.

As long as you know that your window (or instance of CMyDlg) will still be around after posting the message you could simply store the error string in a member variable and read from this in your message handler.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top