みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

Windowsプログラムでのメッセージループ

Microsoft Visual C++6.0でWin32ApplicationでWindowsプログラムを作る勉強を始めました。

『Visual C++ 1 はじめてのWindowsプログラミング』(山本信雄 著)
という本で勉強しています。

WinMain函數の中に次のような「メッセージループ」というものがあるんですね。

while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

本の説明では
「メッセージループとは、GetMessageでメッセージの有無を常に確認しつづけるループです。Windowsプログラムは、何もしていないように見えるときでも常にメッセージループをじっこうしているのです。」
ということです。
また
「もしもメッセージがなければ、GetMessageは他のアプリケーションに処理を讓ります。これによってWindowsのマルチタスクがじつげんされています。」
ともありました。

私が思ったのは、
他のアプリケーションに処理を讓ってしまったら、上の説明にあるような「常にメッセージループをじっこうしている」ことにはならないんではないか、
ということです。
逆に、メッセージがあり續けたら、他のアプリケーションに処理を讓らないのでしょうか。

WindowsのマルチタスクはGetMessageが行っているのではなくて、WindowsというOSが行っているのではないでしょうか。

GetMessageが他のアプリケーションに処理を讓っている間の状態というのは、GetMessage函數がじっこうされている状態なのでしょうか。それとも、その間プログラムは停止しているのでしょうか。停止しているのだとしたら、再開するのはGetMessageの次のTranslateMessageからでしょうか。

編集部に質問を送ったのですが、返事はありません。

初級者ゆえ何か勘違いしているのかもしれません。
よろしくお願いいたします。

投稿日時 - 2002-12-21 07:14:09

QNo.432696

暇なときに回答ください

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

「もしもメッセージがなければ、GetMessageは他のアプリケーションに処理を讓ります。これによってWindowsのマルチタスクがじつげんされています。」

Windows3.1ならそうかもしれない。
95/NT以降はプリエンティブなマルチタスクなのでそんなことはない。

他の本で勉強した方がいいんじゃないでしょうか?
少々値が張りますが、Petzold本がおすすめです。
http://www.ascii.co.jp/books/detail/4-7561/4-7561-3600-1.html
http://www.ascii.co.jp/books/detail/4-7561/4-7561-3601-X.html

投稿日時 - 2002-12-21 12:51:59

お礼

御紹介の本 アスキーの

『プログラミングWindows 第5版』(上・下)
著者等 Charls Petzold著/株式会社ロングテール 長尾高弘訳
シリーズ マイクロソフトプレス プログラミングシリーズ

を讀んでみたいと思います。

ありがとうございました。

投稿日時 - 2002-12-22 10:33:57

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

ちなみに私の例はAとBが同じプロセスにある場合です。

AとBがおなじプロセス(スレッド)上にある場合、つまり同じGetMessageで
監視している場合、
Aは無限ループにおちいっている為、Bは実行されません。
そのプロセスはメッセージをうけとれない為強制終了するしかありません。

しかしAとBが別のプロセス(スレッド)の場合、
つまりそれぞれがGetMessageをもっているならば
Aが永久ループにおちいっていたとしても
OS側でCPUの使用権をBに移してくれます。
A→B→A→B→A→
NT/2000以降(95/98はわかりません)は
細かい単位GetMesageとは関係なくでAとBのCPUの使用権が切り替わります。
ただAによって、CPU率使用率100%のむちゃくちゃ重い状態になりますけど。
詳しいことはしりませんがGetMesageはCPUの使用権を切替えるタイミング
でもあるのだと思います。


実際CPUに処理を待つなんて命令はありません。
OSの中でぐるぐる回っているループの中で
メッセージを監視することで処理を待っているかのように
する事が可能なのです。
Visual C++ 1 はじめてのWindowsプログラミングにも
書かれていたと思いますがSpy++でみるとものすごい量のメッセージ
がOSとやりとりされているのがわかると思います。

投稿日時 - 2002-12-26 13:19:08

補足

正直言うと私はNo.4のご回答は讀んでいて、私の頭ではついていけませんでした。

ご回答No.3の内容とNo.4の内容がどのように關係してくるのか、も わかりませんでした。

ただし、NT/2000はGetMessageと關係なくマルチタスクを行う、という話はわかりました。
これらはプリエンプティブマルチタスクを行うのですよね。

私の知識で言うと、
プリエンプティブなマルチタスクでは、
OSがアプリケーションの状態に依存せずに、強制的にタスク切り替えができるようです。

本でいう「GetMessageのところで他のアプリケーションに処理を譲る」という説明では、
タスクの切り替えがアプリケーションの状態に依存してしまっている。

どうも、本で言っているのは、Windows3.1のような疑似的なマルチタスクの説明であって、
プリエンプティブなマルチタスクの説明ではない、
という氣がしてきました。
そう考えれば、No.1の方の回答内容とも合う。
第一、本では「プリエンプティブなマルチタスクの説明だ」とは明言していない。

もしかしたら理解が間違っているかもしれないけれど、私の知識ではそうとしか思えません。

でも、どうも本全體を眺めてみると、Windows95以降のプリエンプティブなマルチタスクについて解説しているような氣もする。

>詳しいことはしりませんがGetMesageはCPUの使用権を切替えるタイミング
>でもあるのだと思います。

このことが問題であるのですが、もう私には理解の範圍外です。

何度もご回答いただき申し訳ありません。

とりあえず、このサイトが年末年始の休みに入り、區切りがいいので、今回の質問の件は考えるのをやめたいと思います。
新年早々にでも質問を締め切ります。
すみませんが、今回の件については自分でもっと勉強したあとで考えてみたいと思います。
この本(シリーズの1番)は続けて勉強していきたいと思います。

またお世話になるかもしれませんが、そのときはよろしくお願いします。
本當にありがとうございました。

投稿日時 - 2002-12-26 23:11:04

お礼

ありがとうございました。
1月5日締め切らせていただきました。

投稿日時 - 2003-01-05 17:46:14

ANo.3

ちょっと表現が悪かったかもしれないです。再帰的にはよぶことはしません。
GetMessage
は純粋にメッセージをうけとるだけです。
(ちなみにメッセージがなにもなければメッセージがくるまでそのまま待機しています。)

ウインドウズのメッセージは
キュー方式でたまっていきます。
         ←順次イベント実行←
Aでクリック←Aでキー押す←Bにマウス移動←Bでキャンセルボタンを押す

もしもBのウインドウで
while(1){
a=a+1;
}
というコードがVC++の中のソースにあったとすればそのウインドウは
メッセージをうけとる事ができずフリーズしてしまいます。
つまりキャンセルボタンを押したというイベントをキャッチできません。
そこでVC++ではメッセージをうけとる必要があるのですが、
PeekMesageというAPIを使います。

while(1){
a=a+1;
PeekMesage(略・・・);//ここでメッセージがあるか調べる。
if (「キャンセルボタンを押した」){
break;
}
}

#ちなみに普通はこういう処理は負担が大きいので好ましくないようです。

このPeekMesageですがほとんど引数はGetMesageと変わりません。
違いはMSDNにもかいていますが
GetMesageはイベントが発生するのを待ちますが、PeekMesageは待たないというだけです。

投稿日時 - 2002-12-25 10:37:07

補足

>ちょっと表現が悪かったかもしれないです。再帰的にはよぶことはしません。

いいえ、私の知識がないために變なこと書いてすみません。m(__)m

>GetMessage
>は純粋にメッセージをうけとるだけです。
>(ちなみにメッセージがなにもなければメッセージがくるまでそのまま待機しています。)

>GetMesageはイベントが発生するのを待ちますが、PeekMesageは待たないというだけです。

なるほど、わかりました!
メッセージがなければGetMessageは待っているんですね。

つまり、
while(GetMessage(&msg,NULL,0,0))
{
 TranslateMessage(&msg);
 DispatchMessage(&msg);
}
というメッセージループは、メッセージがあればぐるぐる回るけれど、
メッセージがなければGetMessageで止まって待っているんですね!


>ウインドウズのメッセージは
>キュー方式でたまっていきます。

列を作ってたまっているようなイメージですよね。
A・B二つのアプリケーションがあったとしたら、
●Aへのメッセージが次々に續く限り、Aのメッセージループはぐるぐる動き、その間BのメッセージループはGetMessageで止まって待っている。Aへのメッセージが終わって、その後にBへのメッセージが續いてきたら、今度はBのGetMessageが受け取って、Bのメッセージループが回り始める(AのメッセージループはGetMessageで待っている。)
という理解で宜しいでしょうか。


ここまで(複數のアプリケーションのメッセージループどうしの關係)は多分、この理解でいいと思うんです。
問題になるのは、質問にも書いたマルチタスクの件です。

「Windowsプログラムというのはメッセージにたいして反應するようにできている。だから、メッセージがない限り動く必要はないのだから、GetMessageで止まって待っていてもなんの不思議もないはずだ」
とも考えたんです。

でも、アプリケーションAはメッセージにたいする処理がものすごく長いかもしれないではないですか。
その次のメッセージがBにたいするものだったとしても、Aの長い処理を待っているんだろうか。

私が想像するに、次のうちのどちらかが正しいのじゃないかなあ、という氣がするんですが・・・

●「Aへのメッセージが續く間はAの処理だけが行われて、BはGetMessageで待っているだけ」というのはメッセージメッセージループだけ見ればそうだけど、OSから呼ばれるウィンドウプロシージャの部分に關しては、細かい單位でAとBが交代で實行されている

●いや、もともとGetMessageとマルチタスクはまるで別のことであって、メッセージループにしてもウィンドウプロシージャにしても、細かく細かく細切りにされて、交代に實行される。だから、メッセージループがあろうとなかろうと(たとえ、AもBも無限ループを持つアプリケーションであっても)AとBは交代で實行されるんじゃないか。(メッセージループがなければWindowsプログラムとは呼ばないかもしれないけど。)
Aが while(1){a=a+1;} という無限ループを持っていて、Bが while(1) {b=b+1;} という無限ループを持っているとき、
「Aだけが實行されてaだけが増えていき、Bは實行されないのでbはまったく増えない」という話はおかしいのではないか。


ま、私は何か勘違いしているのかもしれないですね。(*^_^*)
初心者ゆえ。

投稿日時 - 2002-12-26 00:40:15

ANo.2

>「GetMessageでメッセージの有無を常に確認しつづけるループです。」
これはその通りだと思います。
もしこのGetMessageがなければ、そのウインドウはメッセージを
うけとる事ができず、フリーズしてしまいます。

問題は「GetMessageは他のアプリケーションに処理を讓ります」の部分ですが
GetMessageは他のアプリケーションに処理を譲るというよりは
自分に処理を回すといった感じでしようか。

#ところで私も(山本信雄 著)の本VC++(1)~(3)まで
#読みました。今でも重宝してます。何はともあれ良い本ですよね。

投稿日時 - 2002-12-24 10:18:38

補足

質問からまる三日たってご回答を頂くのはあまりないですから、大變感謝します。

>>「GetMessageでメッセージの有無を常に確認しつづけるループです。」
>これはその通りだと思います。

私もこの説明はわかります。
whileというのは繰り返し實行されるものだから、ぐるぐる回って實行されるのは初心者でも納得のいく話です。

>問題は「GetMessageは他のアプリケーションに処理を讓ります」の部分ですが

そうですよね。まさしく問題はこの説明にあるわけです。

>GetMessageは他のアプリケーションに処理を譲るというよりは
>自分に処理を回すといった感じでしようか。

私には「自分に処理を回す」というのがわかりません。
「自分に処理を回す」というと、
再歸(さいき)的に、GetMessageの中でGetMessageを呼ぶ、
ということを思ってしまいます。そうなんでしょうか。

できれば「自分に処理を回す」ということがどのようなことなのか、
もっとC言語の初歩的なプログラムで例をあげていただけると幸いなのですが…。


それとも、このシリーズをもっと讀み進めていくとわかる話なのでしょうか。

投稿日時 - 2002-12-24 23:09:47