C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


(過去ログ 76 を表示中)
■44713 / )  Re[6]: VistaとWaitForSingleObjectについて
□投稿者/ とっちゃん (440回)-(2009/12/16(Wed) 14:44:47)
とっちゃん さんの Web サイト
No44708 (kashi さん) に返信
> >>WaitForSingleObject の使い方の応用ですが、タイムアウト時間に 0 を指定することで、対象プロセスが実行中か否かを即座に調べることができます。
> >>WAIT_TIMEOUT_0 が返れば実行中です。
> >>GetExitCodeProcess よりきれいな方法だと思います。
>>
>>あるいは、MsgWaitForMultipleObjectsEx を使った方がいいのかも。
>
> なるほど・・・なんとなくイメージが掴めました。
>
ここにぶら下げておくかな。二重起動についてはとりあえず除外...

どのパターンでやる場合でも...
ボタンハンドラの最初で
親画面EXEのメインウィンドウを無効化する(AfxGetMainWnd()->EnableWindow(FALSE)など)*1
子画面EXEを起動する(CreateProcessなど)*2

1.タイマーピークする場合
SetTimer でタイマーを発動する(0.2秒~0.5秒くらいの間隔で呼び出す)<ウィンドウは何でもよい
タイマーハンドラでは
GetExitCodeProcess で戻り値を取得する(STILL_ACTIVEなら実行中)*2のプロセスハンドルを対象とする
処理が終わっていたら、タイマーを終了し、親画面のメインウィンドウ(*1)をEnableWindow(TRUE)する
戻り値は一切必要ないのであれば WaitForSingleObject(...,0) == WAIT_TIMEOUT でも問題ありません。

2.MsgWaitForMultipleObjects の場合
MsgWaitForMutipleObjects( 1, &(*2のハンドル), FALSE, INFINITE, QS_ALLEVENTS );を行う。
WAIT_OBJECT_0+1 なら、何かメッセージが来たとして
メッセージが来た場合は、メッセージが空になるまでメッセージポンプを回す(MFCなら、while(PeekMessage(...,PM_NOREMOVE)){ theApp.PumpMessage()})
戻り値が、WAIT_OBJECT_0 なら、子画面終了なので、ループを抜けクローズ処理をする(1と段取り的にはほぼ同じ)
EXEが終了してなければ、MsgWaitFor... に戻る

と、こんな感じです。
1の場合、今までの処理とは異なり複数のメッセージに分断されるためちょっと面倒かもしれません。
2の場合は、現在 WaitForSingleObject になっている部分を MsgWaitForMultipleObjects のループに変える形になります(関数に切り出してもいいです)。
処理的には2のほうが変更箇所の範囲も波及エリアも少ないです。
が、ここに書いてある情報+MSDNライブラリでコーディングできないようなら1で作成することをお勧めします。

どちらの場合も、重要なポイントは、親画面のメインウィンドウ(モーダルダイアログから呼ばれているのならそのモーダルダイアログのウィンドウ)を EnableWindow( FALSE )として、無効化しておくことです。
これを行うことにより、メニューや終了コマンドなど一切受け付けなくなります(ダイアログ内の全部の子コントロール類も含む)。


返信 編集キー/


管理者用

- Child Tree -