2016-05-19 1 views
0

私はCWinThreadを使用しています。そして、私はメインのGUIにLPARAMの配列をスレッドに送りました。例、このコードワークス:スレッド上メッセージと共にスレッドに変数をポストするMFCを使用

//On GUI 
char *headData = "L1"; 
PostThreadMessage(threadID,SEND_HEAD, 0, (LPARAM)head); 

void CMyThread::OnSendhead(WPARAM, LPARAM lParam){ 
    char *head = (char*)lParam; 
    if (strcmp(head,"L1")==0){ 
     //This line is reached. 
    } 
    return; 
} 

しかし、私はここで少し変更しますとき:スレッド上

char *head = "L1" 
unsigned char byteHead[3]; 
memcpy(byteHead, head, 3); 
PostThreadMessage(threadID,SEND_HEAD, 0, (LPARAM)byteHead); 

void CMyThread::OnSendhead(WPARAM, LPARAM lParam){ 
    unsigned char* byteHead = (unsigned char*)lParam; 
    char head[3]; 
    memcpy(head, byteHead,3); 
    head[3] = '\0'; 
    if (strcmp(head,"L1")==0){ 
     //This line is nerver reached. 
    } 
    return; 
} 

ifの中のラインは届きません。私は、(LPARAMにキャストせずに)テストのためのGUIにスレッド上のコードを移動し、何事もうまくいきます。だから私はlParamunsigned char*の間にキャストできないと思いますか?なぜ、私はこれをどうやって行うのですか?ありがとうございました

答えて

4

PostMessageメッセージはすぐには処理されませんが、メッセージループで後で取り上げられるようになります。その間にlparamによって指し示されたデータが破壊された場合、それは失敗するでしょう。

最初の例では、文字列リテラルを渡しています。文字列リテラルは、プログラムの全生涯にわたって有効である傾向があります。したがって、これは問題ありません。

2番目の例では、PostMessageを実行した直後におそらく破壊されるローカル変数を使用しています。

代わりにSendMessageを使用してください。すぐに処理されます。または、メッセージが処理されるまで有効であることが保証されている変数を使用します。

+0

をだから、私はにメッセージを送りたいので、私は、messegeがどこに送られるのかを知るためにthreadIDを持っていなければならないので、 'SendMessage'を使用する方法はありません。しかし、変数のために、私はスレッドのGUIのメンバーに触れることは良い練習ではないということについてどこか読んでいますか? –

+0

@TrungNguyenマルチスレッドWindowsプログラムの経験はありませんが、これは地雷が埋まっている領域であり、私はこれまでこれを避けてきました。私は本当にあなたが答えにあるものを超えて信頼できる助言を与えることはできません。 –

+0

ありがとうございます、あなたの答えは正しいです、変数は、スレッドがメッセージをピックアップする前にスクープから外れています。私はmemcpyを使って別の変数に値を格納しています。 –

1

PostMessageまたはPostThreadMessageを使用する場合は、常にboolのようにデータを送信するためにヒープ割り当てメモリを使用し、メッセージハンドラ関数で削除する必要があります。次の例のように、いくつかのstructでメッセージをラップすることができます:

struct MyMsg 
    { 
     int msgCode; // specific to you, and you know underlying datatype 
     char buffer[1024]; // or have a `vector` or dynamic-array you'd manage 
    }; 

送信者:

MyMsg* msg = new MyMsg; 
msg->msgCode = 0x1; // It's a string 
strcpy_s(msg->buffer, "abc"); 
PostThreadMessage(threadID,SEND_HEAD, 0, (LPARAM)msg); 

レシーバー

void CMyThread::OnSendhead(WPARAM, LPARAM lParam) 
{ 
    MyMsg* msg= (MyMsg*)lParam; 
    // use msg 
    delete msg; 
} 
+0

ありがとう、構造体のいい使い方。しかし、送信者の 'msg'が削除されなかった場合、このメモリリークはありますか? –

+0

いいえ、受信者がメモリを削除しています。それは単一のプロセスです。同じプロセスのすべてのスレッドがメモリを完全に共有します。2つのスレッドは異なる呼び出しスタックを持っているので、スタックメモリを別のスレッドに共有することはできません( 'SendMessage'などのブロッキング呼び出しを使用しない限り)。受信機でスマートポインタを使用して、メモリが削除されていることを確認することができます。送信者と受信者間の通信のために、メモリ割り当て/割り当て解除を減らすことができるように、メモリプールを持つこともできます。長い道のり...;) – Ajay

+0

freestoreに値渡しできるものを割り当てる必要はありません。また、データの存続期間を延ばすには、フリーストアだけではありません(オブジェクトの存続期間は、実際には重要です)。静的な記憶期間を持つオブジェクトは別の方法です。さらに、スレッドに投稿されたメッセージは失われる可能性があります(つまり**あなたは**メモリリークの可能性があります)。そして、モジュール境界を越えてCRTリソースを渡すという問題にも触れていません。非常に危険なアドバイス、downvoteにふさわしい。 – IInspectable

関連する問題