質問: vc++ メインループでのイベント監視方法 こんにちは。 vc++2008expressでプログラムをしようと思っている初心者です。 以下、変な疑問があり、お尋ねしたいと思います。 よろしくお願いします。 windowsアプリケーション win32api クラスで別スレッドを作成して、そのスレッドからのイベントを winmainループで受け取る方法ですが 通常皆様はどういう風にするのでしょうか? クラスは、その他のプログラムでも流用可能で様々なアプリに対応しやすいようにしあげたいのですが。。 別スレッドでイベント発生時にwinmainにどのように教えるのが普通のやり方なんでしょうか? 僕の考えでは、winmain関数内のループ内で常時イベント発生していないか 以下のように監視させるか eventloop el; while(getmessage(&msg,null,0,0)) { translatemessage(&msg); dispatchmessage(&msg); if(el::boolevent){ イベント処理へ } } とするのが良いか? これだとクラスの関数、変数の使い方さえ分かるようにしておけば流用は簡単 なのかなと思いますが。。 メインのループ内にこんな監視を入れるようなプログラムをみたことないので ナンセンスなのではと思います。 次に考えられるのは、クラスのイベント発生で作成したsendmessageを送って メッセージ処理でイベント処理をさせるのが良いのかなって思いますが これだと、流用するときに対応したmessage(キュー?ですかね)を作成しないといけなく 私的に分かりにくいなーって思います。。。 変なことで悩んで先に進まないのですが、皆様はどのようにコーディングされるのでしょうか? ちなみにイベントというのは、rs232cで受信があって、そのデータを加工したあとで メモリに格納して格納しましたよってイベントです。 どうかよろしくお願いします。
回答: >メインのループ内にこんな監視を入れるようなプログラム これは普通に行われます。定期的かつ、高頻度で更新しなければならないゲームなんかだと常套手段です。 ただし、getmessage関数はメッセージ来ない間はブロックするので、その間イベント処理が実行されません。 このため、peekmessage関数を使います。 while(true) { if ( peekmessage(&msg,null,0,0,pm_remove) ) { // メッセージを取得した場合0以外が返る if (msg.message == wm_quit ) break; //終了。メッセージループを抜ける。 translatemessage(&msg); dispatchmessage(&msg); continue; } // メッセージがない場合はイベント処理を行う if(el::boolevent){ イベント処理へ } } メッセージループと異なるスレッドからメッセージを送る場合sendmessage関数よりpostmessage関数が推奨されます。 二つの関数はメッセージを送って処理されるまでの仕組みが若干異なります。 表面的な動作的の違いは、sendmessage関数は送ったメッセージが処理されるまでブロックし、postmessage関数はメッセージを送ったら直ちに返ります。 また、メッセージを使ってスレッド間でやりとりする場合、独自のメッセージを定義しなければなりませんが、これにはregisterwindowmessage関数を使います。 wm_user以降の番号で固定で割り当てる方法もありますが、他のライブラリやなんかとバッティングする可能性もあるので汎用性を求めるならあんまりオススメしません。 最後に、ループで処理する場合のイベント通知方法ですが、ブール変数1個ではうまく動かないはずです。 なぜなら、メインスレッド側で、「イベント処理したよ!」という通知をしなければ、「イベント着たよ!」というフラグを解除できず、永久にイベント着たよ状態になってしまいます。 この目的では、とりあえず「イベント同期」という仕組みがウィンドウズにありますので、それを使うことになります。 createevent関数、setevent関数、waitforsingleobject関数あたりを参照してください。 apiの説明はこんなところとして、ループ内で処理するのとメッセージどっちが良いかですが、判断基準の一つは受信したデータをメインループへ送る頻度です。 余りに高頻度にイベント処理が送られると、そのイベントメッセージでメッセージキューが埋まってしまいます。 そうすると、ウィンドウのためのメッセージが処理されづらくなり、反応が悪くなる原因になります。 上のループ内処理の場合、受信スレッドからのイベントを一つ処理するごとに、メッセージを確認しているのでその辺の問題は起こりづらくなります。 わかりやすさとしては、どっちもどっちかなぁ...と。 ただ、ループ内で処理すると、スレッド間同期が絡むと思うのでその辺はメッセージ使うより厄介かもしれません。