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()using 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 の場合、LPARAM で void* キャストとして渡すことができ、クライアントはそれを文字列型にアンキャストします。SendMessage はsynchronousであるため、安全です。

指定されたウィンドウが呼び出しスレッドによって作成された場合、ウィンドウ プロシージャはサブルーチンとして直ちに呼び出されます。指定されたウィンドウが別のスレッドによって作成された場合、システムはそのスレッドに切り替えて、適切なウィンドウ プロシージャを呼び出します。スレッド間で送信されるメッセージは、受信スレッドがメッセージ取得コードを実行する場合にのみ処理されます。受信スレッドがメッセージを処理するまで、送信スレッドはブロックされます

PostMessage を使用する場合は、呼び出しが非同期であるため、明示的なハンドオフを行う必要があります。ヒープに文字列のコピーを作成し、PostMessage を呼び出すことで、削除の責任を呼び出し先 (ダイアログ) に渡します。 .

プロセスから外れた場合 (MyhWnd が別のプロセスに属している場合) は、まったく別の話であり、メッセージをグローバル アトムのようなものにマーシャリングする必要があります。

于 2009-08-24T23:32:34.253 に答える
0

メッセージを投稿した後もウィンドウ (または のインスタンス) がまだ残っていることがわかっている限りCMyDlg、エラー文字列をメンバー変数に格納し、メッセージ ハンドラーでそれを読み取ることができます。

于 2009-08-24T23:52:47.190 に答える