スレッド間のデータのやりとりについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
satoshi

スレッド間のデータのやりとりについて

#1

投稿記事 by satoshi » 17年前

はじめまして。
今、スレッドについて勉強しています。そこでスレッド間のメッセージのやりとりの方法がいまいちよくわかりません…
PostThreadMessage()でメッセージの送信、GetMessage()でメッセージの受信でよろしいのでしょうか?
また、PostThreadMessage()の引数が何をいれたらいぃのかわかりません。
ちなみに送信したい内容はchar型のstrというデータで送信先のスレッド名はanswer_threadです。
詳しい人がいたらご教授をお願いします。また、他の方法でデータのやりとりをしている人がいたら教えてください。

satoshi

Re:スレッド間のデータのやりとりについて

#2

投稿記事 by satoshi » 17年前

質問のところにチェックを付け忘れたました。

Justy

Re:スレッド間のデータのやりとりについて

#3

投稿記事 by Justy » 17年前

 ポスト先のスレッドに予めメッセージキューを作成してあるなら、それでも。

 普通はスレッド間のデータ共有にはクリティカルセクションとか、ミューテックスとか、セマフォなど同期オブジェクトを状況に合わせて使います。


また、PostThreadMessage()の引数が何をいれたらいぃのかわかりません
 送る型は char型の変数 strなら、1バイトなのでさくっと
 PostThreadMessage(ポスト先スレッドID,メッセージID, (WPARAM)str, 0)

 なかんじで良いんじゃないでしょうか。


 あとは MSDNとかは Googleで調べればいろいろもっと詳しいことがわかるかと思います。

satoshi

Re:スレッド間のデータのやりとりについて

#4

投稿記事 by satoshi » 17年前

Justyさん、ご回答いただきありがとうございました。
PostThreadMessage()の引数はそんな内容だったんですね。
ありがとうございました。
ところで、PostThreadMessage()が送信したメッセージが、スレッドで受け取るにはGetMessage()でもよいと仰っていましたが、以下のような使い方でよろしいのでしょうか。
MSG msg;
GetMessage(&msg, NULL, 0, 0);

この場合、GetMessage()の引数であるmsgにstrの内容が格納されるのでしょうか?

Justy

Re:スレッド間のデータのやりとりについて

#5

投稿記事 by Justy » 17年前

GetMessage()でもよいと仰っていましたが、以下のような使い方でよろしいのでしょうか。
 それでいいと思います。

この場合、GetMessage()の引数であるmsgにstrの内容が格納されるのでしょうか?
 MSDNか何かのリファレンスは読みましたか?
 PostThreadMessage()側でどう設定したかにもよりますが、msg構造体の中のメンバ変数に格納されます。
 以下はサンプルです(エラー処理とか何もしてないので注意)。
[color=#d0d0ff" face="monospace]#include <windows.h>
#include <stdio.h>

DWORD MainThreadID;
DWORD WINAPI DoThread(LPVOID x)
{
    char c = 'A';
    do
    {
        PostThreadMessage(MainThreadID, WM_APP, (WPARAM)c, 0);
        Sleep(100);
    } while(isgraph(++c));
    PostThreadMessage(MainThreadID, WM_QUIT, 0, 0);
    return 0;
}

int main(void)
{
    int count = 0; 
    MSG msg;
    MainThreadID = GetCurrentThreadId();
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DoThread, NULL, 0, NULL);
    while(GetMessage(&msg, NULL, 0, 0) > 0)
    {
        if(msg.message == WM_APP)
            printf("[%d] Receive %c\n", ++count, (char)msg.wParam);
    }
    return 0;
}[/color]

satoshi

Re:スレッド間のデータのやりとりについて

#6

投稿記事 by satoshi » 17年前

Justyさん、回答ありがとうございます。
MSDNとかのリファレンスはいろいろ読んでるんですが、いまいち理解出来ないところが多くて‥
今回はサンプルプログラムまで載せてくれて、本当にありがとうございました。
あとは、なんとか理解してやってみます。
ご回答ほんとうにありがとうございました。

satoshi

Re:スレッド間のデータのやりとりについて

#7

投稿記事 by satoshi » 17年前

わからないことが出てきたので、また質問させていただきます。
今、main()のスレッドで、char regstrに格納されたデータをans_thread()スレッドに送りたいんですが、
ポストの書式は、PostThreadMessage(at_id,WM_APP,(WPARAM)regstr,0);でよろしいのでしょうか?
また、受け取る側のスレッド(ans_thread())は、MSG msg;を宣言してGetMessage(&msg,NULL,0,0);でよろしいのでしょうか?
ちなみに、受け取ったデータをsend()で送りたいんですが、send(sock,msg.wParam,strlen(msg.wParam), 0);なかたちでよろしいのでしょうか…?このようにすると、「2 番目の引数を 'WPARAM' から 'const char *' に変換できません。」というエラーが発生します。
MSDNのリファレンスを見たのですがやはり理解に苦しみまして…
わかる人がいたらお願いします。

mas

Re:スレッド間のデータのやりとりについて

#8

投稿記事 by mas » 17年前

> strlen(msg.wParam)

とありますが、msg.wParamがWPARAM型であるのに対して、strlenの引数はchar*です。
従ってキャストする必要あります。

が、この場合msg.wParamはchar型のregstrですよね?
それなら文字列ではなくsizeof(char)=1byte固定なので、

send(sock,msg.wParam,1, 0);

でいいと思います。

# 上のほうを見ていて気になったのですが、
# 実はcharじゃなくてchar*(文字列)のやり取りをするつもりでということはないですよね?

Justy

Re:スレッド間のデータのやりとりについて

#9

投稿記事 by Justy » 17年前

@masさん
実はcharじゃなくてchar*(文字列)のやり取りをするつもり~
 strlenを見て私もそんな気がしてきました。


@satoshiさん
ポストの書式は、PostThreadMessage(at_id,WM_APP,(WPARAM)regstr,0);でよろしいのでしょうか?
 regstrの型が char(1バイト)ならOK。
 ただ WM_APPのIDに関しては 0x8000~0xBFFFの間で自由にIDを設定できるので、WM_APPのまま使わないで、自前で別定義を用意した方がいいでしょう(http://yokohama.cool.ne.jp/chokuto/uraw ... _USER.html)。


受け取る側のスレッド(ans_thread())は~でよろしいのでしょうか?
 多分それでいいと思いますが、実際のところはその周辺をどう書いているのかにも依存します。


# もし万が一、送りたい型が charではなく char*ないしは char[/url]であるなら。
 PostThreadMessage()では WPARAMと LPARAMの2つのパラメータしか送れません。
 つまり合わせて最大8バイトまでです。
 文字列を送りたいのであれば、ちょっと工夫が必要になります。

satoshi

Re:スレッド間のデータのやりとりについて

#10

投稿記事 by satoshi » 17年前

masさん、Justyさん回答していただきありがとうございます。

>masさん
>実はcharじゃなくてchar*(文字列)のやり取りをするつもりでということはないですよね?

申し訳ありません。実はchar*でのやり取りでした。

>Justyさん
>もし万が一、送りたい型が charではなく char*ないしは char[/url]であるなら。
PostThreadMessage()では WPARAMと LPARAMの2つのパラメータしか送れません。
つまり合わせて最大8バイトまでです。

最大8バイトまでなんですか!?送るのは結構長い文字列なんですよね…
その場合は8バイトづつに分けて送るという感じなるんですか?

無知で申し訳ありません。

Justy

Re:スレッド間のデータのやりとりについて

#11

投稿記事 by Justy » 17年前

>最大8バイトまでなんですか!?送るのは結構長い文字列なんですよね…

 ぱっと思いついたのを少しサンプルを改造して作ってみました。
 動作を追ってみてください。
[color=#d0d0ff" face="monospace]#include <windows.h>
#include <stdio.h>
#include <time.h>

static DWORD MainThreadID;

#define WM_APP_STRING   (WM_APP + 10)

DWORD WINAPI DoThread(LPVOID x)
{
    static const char * const str_tbl[/url]
        = { "ABCDEFG", "abcdefg", "12345", "67890", "3.1415926535" };
    unsigned counter = 50;
    do
    {
        unsigned index = rand() % 5;
        char *buff = (char*)malloc(5 + strlen(str_tbl[index]) + 1);
        sprintf(buff, "%2d : %s", counter, str_tbl[index]);
        PostThreadMessage(MainThreadID, WM_APP_STRING, 0, (LPARAM)buff);
        Sleep(100);
    } while(--counter);
    PostThreadMessage(MainThreadID, WM_QUIT, 0, 0);
    return 0;
}

int main(void)
{
    int count = 0; 
    MSG msg;
    MainThreadID = GetCurrentThreadId();
    srand((unsigned)time(NULL));
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DoThread, NULL, 0, NULL);
    
    while(GetMessage(&msg, NULL, 0, 0) > 0)
    {
        if(msg.message == WM_APP_STRING)
        {
            char *receive_str = (char*)msg.lParam;
            printf("[%d] Receive %s\n", ++count, receive_str);
            free(receive_str);
         }
    }
    return 0;
}[/color]
 Post側で mallocしたバッファに文字列を入れ、Post先で使い終わったら解放しています。
 この方法なら mallocできる限り多少文字列が長くても問題はないですが、決してメッセージの取りこぼしがあってはいけません。
 あった場合、メモリリークになります。

 この程度の文字列なら無理にメッセージで送らなくてもクリティカルセクション・セマフォとかの同期オブジェクトを使った方がいいかと思います。

satoshi

Re:スレッド間のデータのやりとりについて

#12

投稿記事 by satoshi » 17年前

Justyさん、ありがとうございます。
サンプルまで載せていただきありがとうございます。
クリティカルセクションやセフォマとかでも出来るんですね。
勉強になります。そこらへんも調べてまた頑張ってみます。
ご回答ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る