16

在我的应用程序中,我想从不同的线程向对话框发送消息。我想将 std::exception 派生类引用传递给对话框。

像这样的东西:

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

我想在我的对话框中接收消息并显示其中的错误 the_exception.error_string()

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

我想通过std::string the_exception.error_string()使用 PostMessage 也可以。

4

3 回答 3

13

您不能在 PostMessage 中传递字符串的地址,因为该字符串可能在堆栈上是线程本地的。当另一个线程捡起它时,它可能已经被破坏了。

相反,您应该通过 new 创建一个新的字符串或异常对象并将其地址传递给另一个线程(通过 PostMessage 中的 WPARAM 或 LPARAM 参数)。然后另一个线程拥有该对象并负责销毁它。

下面是一些示例代码,展示了如何做到这一点:

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


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

    // Do stuff with message

    return 0;
}
于 2009-08-24T23:34:01.970 回答
2

只要您在一个进程中,只需传递一个 void* 指针并注意对象生命周期就足够了。

如果是 SendMessage,您可以将其作为 void* 强制转换在 LPARAM 中传递,然后客户端将其取消转换回您的字符串类型。因为 SendMessage 是同步的,所以你是安全的:

如果指定的窗口是由调用线程创建的,则窗口过程作为子例程立即调用。如果指定的窗口是由不同的线程创建的,则系统切换到该线程并调用适当的窗口过程。只有当接收线程执行消息检索代码时,才会处理线程之间发送的消息。发送线程被阻塞,直到接收线程处理完消息

如果您想使用 PostMessage,那么您必须进行显式切换,因为调用是异步的:在堆上复制字符串并通过调用 PostMessage,您已将删除责任传递给 calee(对话框) .

如果您退出进程(MyhWnd 属于不同的进程),那么情况就完全不同了,您将不得不将您的消息编组为类似于全局原子的东西。

于 2009-08-24T23:32:34.253 回答
0

只要您知道您的窗口(或 的实例CMyDlg)在发布消息后仍然存在,您就可以简单地将错误字符串存储在成员变量中并在消息处理程序中从中读取。

于 2009-08-24T23:52:47.190 回答