• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:VC++ メインループでのイベント監視方法)

VC++メインループでのイベント監視方法

このQ&Aのポイント
  • VC++初心者がWindowsアプリケーションでのイベント監視方法を尋ねています。
  • クラスで別スレッドを作成し、WinMainループでイベントを受け取る方法についてのアドバイスを求めています。
  • イベントの発生を監視するための方法として、メインループ内でのイベント監視やSendMessageを使用する方法に悩んでいます。

質問者が選んだベストアンサー

  • ベストアンサー
  • axsies
  • ベストアンサー率64% (38/59)
回答No.1

>メインのループ内にこんな監視を入れるようなプログラム これは普通に行われます。定期的かつ、高頻度で更新しなければならないゲームなんかだと常套手段です。 ただし、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の説明はこんなところとして、ループ内で処理するのとメッセージどっちが良いかですが、判断基準の一つは受信したデータをメインループへ送る頻度です。 余りに高頻度にイベント処理が送られると、そのイベントメッセージでメッセージキューが埋まってしまいます。 そうすると、ウィンドウのためのメッセージが処理されづらくなり、反応が悪くなる原因になります。 上のループ内処理の場合、受信スレッドからのイベントを一つ処理するごとに、メッセージを確認しているのでその辺の問題は起こりづらくなります。 わかりやすさとしては、どっちもどっちかなぁ…と。 ただ、ループ内で処理すると、スレッド間同期が絡むと思うのでその辺はメッセージ使うより厄介かもしれません。

t-osk1109
質問者

お礼

早々の回答ありがとうございました。だいぶ悩んでおりお礼が遅くなりすいません。ループで監視するか、メッセージにするか。。。 大変、参考になるご教示ありがとうございます。 かなりの初心者ですので、まだ慣れない言葉もあり勉強します。 ありがとうございました。

その他の回答 (3)

  • gentoo314
  • ベストアンサー率41% (15/36)
回答No.4

スレッド間の情報の受け渡しに方法には、大きく分けて2種類あります。 ・メッセージ ・同期オブジェクト 今回の質問ではメッセージを前提として書かれていますが、妥当でしょうか。 というところから設計します。 私の使い分け方は、GUI関連ならメッセージ、それ以外なら同期オブジェクトで検討します。 それはさておき、メッセージの場合でしたら、ワーカースレッドからPostMessage()でメッセージを投げるのがシンプルです。 メッセージループ内で、フラグチェックはビジーループ(CPU使用率100%)になるので、NGです。 スレッドが待ち状態の時に、いかに処理を止めるかも考慮してください。 メッセージなら GetMessage(), 同期オブジェクトなら WaitForSingleObject() など、待ち中にCPU資源 を消費しないAPIが用意されています。

t-osk1109
質問者

お礼

早々の回答ありがとうございました。だいぶ悩んでおりお礼が遅くなりすいません。ループで監視するか、メッセージにするか。。。 大変、参考になるご教示ありがとうございます。 待ち中にCPU資源を使用しない方法として、まだ悩んでおりますが。。。 また、質問させていただきます。 ありがとうございました。

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.3

> 別スレッドでイベント発生時にWinMainにどのように教えるのが普通のやり方なんでしょうか? 設計思想と絡んでくると思うので、やりたいように、というのが答えなんですが、 考え方のとっかかりとして、一例を挙げてみます。 例えば、会社の役職を考えてみてください。 「社長」「部長」「課長」「担当」などがありますが、 このような概念を、設計に持ち込んでみます。 以下は、私が勝手に定義してみました。 社長→OS 部長→アプリケーション(WinMain) 課長→rs232cの受信状況を管理するスレッド 担当→rs232cの受信処理を行うスレッド どの仕事を誰の責任範囲でやるか考えてみると、 社長が担当の状況を知っているべきか?→No 部長が、担当のことを知っているべきか?→No などという風に考えることができます。 >その他のプログラムでも流用可能で様々なアプリに対応しやすいように あなたは、この「責任範囲の分担」について悩んでいるのではないでしょうか。 例えば、WinMainで、受信スレッドの処理経過を把握するとなると、 他のアプリで受信機能を利用しようとしたときに、WinMainからソースコードを 抜き出して、持っていかなければなりません。あまり美しくはないですね。 上記のように、私なら「受信状況を管理するスレッド」を別で用意して、 必要に応じて、受信状況の問い合わせに応じられるようなメソッドを用意しておきます。 > これだと、流用するときに対応したMessage(キュー?ですかね)を作成しないといけなく > 私的に分かりにくいなーって思います。。。 それは慣れの問題かと思いますよ。 もし、その場限りで使い捨てるようなプログラムであれば、テキトーに作成すれば 良いですし、流用できるような構造にするなら、ある程度、綺麗に設計する 必要が出ることと思います。 プレハブ小屋を建てるのと、一戸建てを建てるのに、緻密な設計が必要かどうか、 と同じです。 前回のご質問から、1オブジェクトが1スレッドの面倒を見るのは、 分かりやすくて、不具合が起きた時にも、対処し易いでしょう。 スレッド間の通信を行うなら、そのように、責任範囲を明確にしておかないと、 流用することが難しくなったり、不具合が起きた際の原因究明が難しくなります。 その辺りを、どう設計するかが、腕の見せ所かと思います。 スレッド間のメッセージ通信については、#1の方の情報などを参考にしてみてください。

t-osk1109
質問者

お礼

早々の回答ありがとうございました。 だいぶ悩んでおりお礼が遅くなりすいません。 ループで監視するか、メッセージにするか。。。 大変、参考になるご教示ありがとうございます。 それぞれの役割を考えてコーディングしたいと思います。 素人なのに、簡単に組めばいいのに、何か譲れないものがあり、未だに何もできないで試行錯誤のみで終わってます。 管理スレッドなど作成してみたいと思います。 No.1の方への補足欄に間違って本お礼を入力してしまいました。 大変失礼致しました。ありがとうございました。

  • axsies
  • ベストアンサー率64% (38/59)
回答No.2

No1の追記です。 >最後に、ループで処理する場合のイベント通知方法ですが、ブール変数1個ではうまく動かないはずです。 とか書いてしまいましたが、ここは問題にはなりませんね。完全にミスです。 同期イベントも、プロセス超えるわけではないのですし、メッセージ処理するために常にループしてるので大げさでした。 (イベントが無い間何もすることが無い場合、ビジーループになるのでWaitForSingleObject関数のようなOSの待機命令を使った方がシステム全体としては効率的ですが) 再考してみると、ウィンドウメッセージを使った場合でも、引数に渡せるのはwParamとlParamだけなので、データがこの8バイトに収まらないのなら、バッファから引き出すときに同期が必要です。 結局、同期処理の複雑さとしてはどちらも変わらないかもしれません。 また、通信開始、データ受信、通信終了、などのイベントは複数あると思いますが、この辺の通知する仕組みを実装する手間は、ウィンドウズのメッセージを使った方が省けますし、一貫してウィンドウプロシージャで処理できるので、把握はしやすいかもしれません。 整理し切れていない回答になってしまいました。申し訳ありません。 結構なボリュームになってしまったので、個々の説明が雑で、参考URLも載せられませんでしたが、ご了承ください。

t-osk1109
質問者

お礼

早々の回答ありがとうございました。だいぶ悩んでおりお礼が遅くなりすいません。ループで監視するか、メッセージにするか。。。 大変、参考になるご教示ありがとうございます。 それぞれの役割を考えてコーディングしたいと思います。 素人なのに、簡単に組めばいいのに、何か譲れないものがあり、未だに何もできないで試行錯誤のみで終わってます。 管理スレッドなど作成してみたいと思います。

関連するQ&A