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からでしょうか。
編集部に質問を送ったのですが、返事はありません。
初級者ゆえ何か勘違いしているのかもしれません。
よろしくお願いいたします。
No.1ベストアンサー
- 回答日時:
「もしもメッセージがなければ、GetMessageは他のアプリケーションに処理を讓ります。
これによってWindowsのマルチタスクがじつげんされています。」Windows3.1ならそうかもしれない。
95/NT以降はプリエンティブなマルチタスクなのでそんなことはない。
他の本で勉強した方がいいんじゃないでしょうか?
少々値が張りますが、Petzold本がおすすめです。
http://www.ascii.co.jp/books/detail/4-7561/4-756 …
http://www.ascii.co.jp/books/detail/4-7561/4-756 …
御紹介の本 アスキーの
『プログラミングWindows 第5版』(上・下)
著者等 Charls Petzold著/株式会社ロングテール 長尾高弘訳
シリーズ マイクロソフトプレス プログラミングシリーズ
を讀んでみたいと思います。
ありがとうございました。
No.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とやりとりされているのがわかると思います。
この回答への補足
正直言うと私はNo.4のご回答は讀んでいて、私の頭ではついていけませんでした。
ご回答No.3の内容とNo.4の内容がどのように關係してくるのか、も わかりませんでした。
ただし、NT/2000はGetMessageと關係なくマルチタスクを行う、という話はわかりました。
これらはプリエンプティブマルチタスクを行うのですよね。
私の知識で言うと、
プリエンプティブなマルチタスクでは、
OSがアプリケーションの状態に依存せずに、強制的にタスク切り替えができるようです。
本でいう「GetMessageのところで他のアプリケーションに処理を譲る」という説明では、
タスクの切り替えがアプリケーションの状態に依存してしまっている。
どうも、本で言っているのは、Windows3.1のような疑似的なマルチタスクの説明であって、
プリエンプティブなマルチタスクの説明ではない、
という氣がしてきました。
そう考えれば、No.1の方の回答内容とも合う。
第一、本では「プリエンプティブなマルチタスクの説明だ」とは明言していない。
もしかしたら理解が間違っているかもしれないけれど、私の知識ではそうとしか思えません。
でも、どうも本全體を眺めてみると、Windows95以降のプリエンプティブなマルチタスクについて解説しているような氣もする。
>詳しいことはしりませんがGetMesageはCPUの使用権を切替えるタイミング
>でもあるのだと思います。
このことが問題であるのですが、もう私には理解の範圍外です。
何度もご回答いただき申し訳ありません。
とりあえず、このサイトが年末年始の休みに入り、區切りがいいので、今回の質問の件は考えるのをやめたいと思います。
新年早々にでも質問を締め切ります。
すみませんが、今回の件については自分でもっと勉強したあとで考えてみたいと思います。
この本(シリーズの1番)は続けて勉強していきたいと思います。
またお世話になるかもしれませんが、そのときはよろしくお願いします。
本當にありがとうございました。
No.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は待たないというだけです。
この回答への補足
>ちょっと表現が悪かったかもしれないです。再帰的にはよぶことはしません。
いいえ、私の知識がないために變なこと書いてすみません。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はまったく増えない」という話はおかしいのではないか。
ま、私は何か勘違いしているのかもしれないですね。(*^_^*)
初心者ゆえ。
No.2
- 回答日時:
>「GetMessageでメッセージの有無を常に確認しつづけるループです。
」これはその通りだと思います。
もしこのGetMessageがなければ、そのウインドウはメッセージを
うけとる事ができず、フリーズしてしまいます。
問題は「GetMessageは他のアプリケーションに処理を讓ります」の部分ですが
GetMessageは他のアプリケーションに処理を譲るというよりは
自分に処理を回すといった感じでしようか。
#ところで私も(山本信雄 著)の本VC++(1)~(3)まで
#読みました。今でも重宝してます。何はともあれ良い本ですよね。
この回答への補足
質問からまる三日たってご回答を頂くのはあまりないですから、大變感謝します。
>>「GetMessageでメッセージの有無を常に確認しつづけるループです。」
>これはその通りだと思います。
私もこの説明はわかります。
whileというのは繰り返し實行されるものだから、ぐるぐる回って實行されるのは初心者でも納得のいく話です。
>問題は「GetMessageは他のアプリケーションに処理を讓ります」の部分ですが
そうですよね。まさしく問題はこの説明にあるわけです。
>GetMessageは他のアプリケーションに処理を譲るというよりは
>自分に処理を回すといった感じでしようか。
私には「自分に処理を回す」というのがわかりません。
「自分に処理を回す」というと、
再歸(さいき)的に、GetMessageの中でGetMessageを呼ぶ、
ということを思ってしまいます。そうなんでしょうか。
できれば「自分に処理を回す」ということがどのようなことなのか、
もっとC言語の初歩的なプログラムで例をあげていただけると幸いなのですが…。
それとも、このシリーズをもっと讀み進めていくとわかる話なのでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBSの処理中一旦処理を止めて再...
-
Loopとフリーズ
-
vb.net イベントが完全に終了...
-
VBA kernel32 の意味
-
sprintf()の使用方法
-
VCでウエイトをミリ秒でかけ...
-
Timerのカウントダウンのしかた...
-
VB Loopを一時停止し再開あるい...
-
左シングルクリックとダブルク...
-
VBA メッセージボックスを自動...
-
Application.ScreenUpdating=Fa...
-
VBSで応答不要のメッセージボッ...
-
メッセージボックスのボタン名変更
-
beforecloseの中からの抜け出し方
-
ボタンが押された事を検知する...
-
DoEvents
-
VBA、UserFormを前面に出力して...
-
マルチスレッドを実現したい
-
Macターミナルで実行中のプログ...
-
バックグラウンドのプロセスの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBSの処理中一旦処理を止めて再...
-
メッセージボックスのボタン名変更
-
ACCESS側からEXCELの書式を設定...
-
VBA メッセージボックスを自動...
-
VBA kernel32 の意味
-
Application.ScreenUpdating=Fa...
-
VBA、UserFormを前面に出力して...
-
Excel VBA で処理中断(DoEvents...
-
エクセルVBAでクリップボード内...
-
VBSで応答不要のメッセージボッ...
-
Excel VBA 自動的に閉じるMsgBox
-
VCでウエイトをミリ秒でかけ...
-
キーボード入力、マウス操作を...
-
C#で処理中画面を表示したい。
-
【C#】 あるイベントから別イ...
-
マウスのクリックを無視したい
-
【MFC】イベントの無効化について
-
Excelのワークシートに行を挿入...
-
アクセスでのキー送信について
-
シャットダウン時のExcel強制終...
おすすめ情報