
こんにちは。
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も見ています
-
VC++スレッドの正しい終了のさせかた
C言語・C++・C#
-
WinAPI「MsgWaitForMultipleObjectsについて」
C言語・C++・C#
-
エディットボックスの入力制限について
C言語・C++・C#
-
-
4
対象のアプリケーションが終了するまで起動し続ける
C言語・C++・C#
-
5
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
6
CString から LPCTSTRの型に変換
C言語・C++・C#
-
7
CStringをwchar_tに変換したい
C言語・C++・C#
-
8
ShellExecuteEx→WaitForSingleObjectで返ってこない
C言語・C++・C#
-
9
CloseHandle()
C言語・C++・C#
-
10
スレッドの終了の仕方
C言語・C++・C#
-
11
DWORDの実際の型は何でしょうか
C言語・C++・C#
-
12
std::stringからLPCWSTR型への変換
C言語・C++・C#
-
13
待機関数(WaitForMultipleObjects等)について教えてください
C言語・C++・C#
-
14
静的でないメンバ関数の呼び出しが正しくありません
C言語・C++・C#
-
15
スレッドの終了はどうやるんですか?
C言語・C++・C#
-
16
画面を強制的に再描画させる方法
C言語・C++・C#
-
17
unsigned long long 型のフォーマット指定子
C言語・C++・C#
-
18
(マルチスレッド)_beginthreadexに複数の引数を渡す
C言語・C++・C#
-
19
ダイアログボックスで指定したサイズどおり表示されない
C言語・C++・C#
-
20
多重定義が起きている?--lnk2005エラー:VC++
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
スレッドの監視方法について
-
メインダイアログが最背面に表...
-
C# スレッド終了の監視について
-
スレッドにて同一メモリの書き...
-
VB2005 シリアル通信のClose処理
-
マルチスレッドプログラミング...
-
別スレッドのデータを受信できない
-
特定のスレッドの破棄
-
待機関数(WaitForMultipleObjec...
-
VC++スレッドの正しい終了のさ...
-
別スレッドからのフォームのテ...
-
DirectX LPDIRECT3DDEVICE9のマ...
-
スレッドでのモードレスダイア...
-
メモリアクセスの競合について
-
グローバル変数が正常に参照で...
-
_beginthreadexで生成したスレ...
-
Windows上で、シグナル(SIGTERM...
-
同一スレッドで、ロックをかけ...
-
.netアプリへのSendMessageでフ...
-
スレッドの終了の仕方
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
スレッドの監視方法について
-
VC++スレッドの正しい終了のさ...
-
スレッドの終了の仕方
-
WaitForSingleObjectの使い方に...
-
Windows上で、シグナル(SIGTERM...
-
別スレッドのデータを受信できない
-
スレッドの安全な終了のさせ方
-
スレッドにて同一メモリの書き...
-
別スレッドからメインダイアロ...
-
マルチスレッドのスレッド数を...
-
C# スレッド終了の監視について
-
MFC通信プログラムマルチスレッ...
-
Linuxでスレッド優先度って変え...
-
メインダイアログが最背面に表...
-
スレッドの終了はどうやるんで...
-
CWnd::OnTimerのスレッドの取得
-
C# スレッドから親ウィンドウへ...
-
メインスレッドのPostMessageと...
-
msec単位のWait Timerが作れない!
-
.NetのBackgroundWorkerクラス...
おすすめ情報