
こんにちは。
WaitForSingleObjectを使って、スレッドがシグナル状態になるまで待機するために、以下のようにコーディングしました。
WaitForSingleObject( threadHandle, INFINITE );
ところが上記だと、スレッドが正常にシグナル状態にならなかった場合に、永遠に待ち続けフリーズしてしまう可能性があること以下のサイトで知りました。
http://hitokuso.kicks-ass.org/progtips.html#1
while( ::WaitForSingleObject( threadHandle, 50 ) == WAIT_TIMEOUT )
{
MSG msg;
::GetMessage( &msg, NULL, 0, 0 );
if( !IsDialogMessage( &msg ) )// ダイアログ内の場合
{
::TranslateMessage( &msg );
::DispatchMessage( &msg );
}
}
上記のようにwhileループで回し、タイムアウトだったらメッセージを処理しているようなのですが、タイムアウト時間として50ミリ秒を指定しているので、一瞬だけ待ってすぐにメッセージ処理を継続しているような気がします。これでは、スレッドがシグナル状態になるまで待たないような気がするのですが…
まだまだ知識不足のため、見当違いな疑問を持っているのかもしれませんが、どなたかアドバイス・ご教授をお願いいたします。
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
上記のサンプルには2点間違いがあります。
1. GetMessage() 関数はなんらかしらのメッセージが届くまで制御を戻しません。そのため、スレッドが終了したのにメッセージが届かなくなるまでは処理がブロックされてしまいます。代わりにメッセージが「あれば」取りに行く PeekMessage() 関数を使用します。
2. メッセージ処理を行いながら待機する場合には WaitForSingleObject() 関数ではなく、MsgWaitForMultipleObjects() 関数を使用します。
そのため、質問にありますスレッドがシグナル状態になるまで待つようにするには、
::GetMessage( &msg, NULL, 0, 0 );
を
while( ::PeekMessage( &msg, NULL, 0, 0 ) )
に変更すればよいかと思います。
なお、2. の問題については、タイムアウト時間をより長く設定するために必要な処理ですので、気が向いたら対策していただければよいと思います。対策方法は若干複雑になりますが、以下のようになります。
::WaitForSingleObject( threadHandle, 50 )
を
::MsgWaitForMultipleObjects(1, &threadHandle, FALSE, INFINITE, QS_ALLINPUT )
に変更して、
* MsgWaitForMultipleObjects()の戻り値が 0 の場合はスレッドが終了したため、ループを抜けます。
* 戻り値が 1 の場合は、PeekMessage() 以下の処理を実行します。
* それ以外の場合には、エラーが発生していますのでエラー処理を実行してループを抜けます。
No.3
- 回答日時:
#1の方の回答の通りですが、少し補足します。
URLの説明は、スレッド中でSendMessage()を使っているとそのメッセージを受け取ってやらないとスレッドが終了しないので、スレッドを終了させるためメッセージを受け取ってやる例として質問にあるコードをあげてあるようです。
実際は、そのスレッドが何をしているかによります。
直接SendMessage()は呼んでいなくても、間接的に呼ばれる可能性もありますから、あまり単純にはこうしなくてはならないとは言えないと思います。
まあ、とりあえずは、画面の表示などの変更があれば使っていると思えばいいかなと。
WaitForSingleObject()はシグナル状態になった場合と、TIMEOUTした場合で戻り値が違います。
質問にあるソースではタイムアウトの場合にwhileループを実行しますから、
結果スレッドがシグナル状態になると戻り値が変化してwhileループを抜けるわけです。
つまり、スレッドを待っていることになります。
whileループの中は実行されてますから待っていないと言えなくもないですが、TIMEOUTさせることは待ちきれずに待つのをやめることですからね。
No.2
- 回答日時:
>永遠に待ち続けフリーズしてしまう可能性があること
それはただのプログラム上のバグです。
WaitForSingleObject(WaitForMultipleObjects)
はCPUに少ない負担で待ち状態にできるのがメリットです。
ですからシグナル状態まで必ず待たせたいのなら
INFINITEを指定してください。
WaitForSingleObject( threadHandle, 50 )
これだと50ミリ秒間隔で通過します。
>一瞬だけ待ってすぐにメッセージ処理を継続しているような気がします
コードを見るとそれを意図しているコードにしかみえません。
while( ::WaitForSingleObject( threadHandle, 50 ) == WAIT_TIMEOUT )
これだと
while(true){
Sleep(50);
(略)
}
と似たような動作になります。
シグナル状態で通過させたいなら
::WaitForSingleObject( threadHandle, 50 ) == WAIT_OBJECT_0
です。
No.1
- 回答日時:
このコードの場合、WaitForSingleObject()を一瞬で通過するのは確かですが、
同様にメッセージ処理部分も一瞬で通過しています。つまりwhile文によって、
WaitForSingleObject()→メッセージ処理→WaitForSingleObject()→メッセージ処理→・・・
というループ処理が延々繰り返されている事になります。
スレッド側がシグナル状態になれば、WaitForSingleObject()でそれを検知しますから
ループを抜けることができるわけです。
WaitForSingleObject()でINFINITEを指定した場合との違いはメッセージを処理するかどうかだけで
シグナル状態になるまで待機する事には変わりありませんから、
もしスレッド側が正常終了しなかった場合には、このコードでも無限ループします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Excel(エクセル) Excel-VBAの「しばらくお待ちください」のダイアログが自動的に閉じない 2 2023/05/24 15:31
- JavaScript javascriptで入力フォームが空欄の時にアラートによるエラーを出すコードを書いています。 2 2023/06/13 17:58
- JavaScript セレクトを全て選択されていないと、文字によるエラーメッセージを表示させるコードを調べています 2 2023/06/22 15:48
- Excel(エクセル) エクセルVBA Msgboxでの変数の活用 4 2023/07/23 08:33
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- PHP if(preg_match("/[^0-9]/",$gu_d)){意味を教えてください。 1 2022/05/06 05:37
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- JavaScript Javascriptが機能せず原因が分からないので教えて頂きたいです 3 2023/06/04 14:50
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
このQ&Aを見た人はこんなQ&Aも見ています
-
対象のアプリケーションが終了するまで起動し続ける
C言語・C++・C#
-
WinAPI「MsgWaitForMultipleObjectsについて」
C言語・C++・C#
-
VC++スレッドの正しい終了のさせかた
C言語・C++・C#
-
-
4
エディットボックスの入力制限について
C言語・C++・C#
-
5
DWORDの実際の型は何でしょうか
C言語・C++・C#
-
6
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
7
CloseHandle()
C言語・C++・C#
-
8
ShellExecuteEx→WaitForSingleObjectで返ってこない
C言語・C++・C#
-
9
std::stringからLPCWSTR型への変換
C言語・C++・C#
-
10
静的でないメンバ関数の呼び出しが正しくありません
C言語・C++・C#
-
11
画面を強制的に再描画させる方法
C言語・C++・C#
-
12
MFC ダイアログ上のID取得について
C言語・C++・C#
-
13
スレッドの終了の仕方
C言語・C++・C#
-
14
Debug Assertion Failed?
C言語・C++・C#
-
15
c++ cmathとmath.h
C言語・C++・C#
-
16
ハンドルはポインタか
C言語・C++・C#
-
17
char*を初期化したいのですが
C言語・C++・C#
-
18
PostMessageの連続送信
C言語・C++・C#
-
19
プロセスIDからウィンドウハンドルを取得する方法
C言語・C++・C#
-
20
API関数 GetExitCodeProcess
Visual Basic(VBA)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スレッド内のCString使用
-
Windows上で、シグナル(SIGTERM...
-
グローバルフック
-
スレッドの監視方法について
-
WaitForSingleObjectの使い方に...
-
スレッド終了を待つ間に開放さ...
-
DirectX キーが入力されるまで...
-
同一スレッドで、ロックをかけ...
-
メインダイアログが最背面に表...
-
マルチスレッド内のループについて
-
【VC++6.0(MFC)】スレッドの呼...
-
Macターミナルで実行中のプログ...
-
C言語で、メモリを解放しないで...
-
C言語で途中までしか、プログラ...
-
TCP/IP通信時のサーバーからの受信
-
メモリのセグメント違反の解決...
-
メッセージボックスのボタン名変更
-
レジスタマップって何ですか?
-
VBA kernel32 の意味
-
10進ベーシックで質問です。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
スレッドの監視方法について
-
VC++スレッドの正しい終了のさ...
-
スレッドにて同一メモリの書き...
-
スレッドの終了の仕方
-
VB2005 シリアル通信のClose処理
-
WaitForSingleObjectの使い方に...
-
別スレッドのデータを受信できない
-
同一スレッドで、ロックをかけ...
-
CWnd::OnTimerのスレッドの取得
-
スレッドの安全な終了のさせ方
-
メインダイアログが最背面に表...
-
スレッド一覧の取得
-
Windows上で、シグナル(SIGTERM...
-
C言語で一定時間待機後、再実行
-
C#でスレッド実行中のイベント...
-
複数スレッドを動作させるのに...
-
.netアプリへのSendMessageでフ...
-
DirectX LPDIRECT3DDEVICE9のマ...
-
スレッド内でコントロールやWin...
-
DirectX 11のConsntanBuffer
おすすめ情報