WaitForSingleObject関数の説明は次のMSのサイトにあります。
http://msdn.microsoft.com/ja-jp/library/cc429427.aspx
winbase.hファイルで宣言されているようです。
戻り値は,
WAIT_ABANDONED = 0x0080
WAIT_OBJECT_0 = 0x0000
WAIT_TIMEOUT = 0x0102
のようですから,タイムアウトは10進数で258ですね。
ついでに,waveInのエラーメッセージですが,次のような感じで表示してみたらいかがですか。
#include <mmsystem.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
char num[5];
char errormsg[256];
int tmp;
for(int i=1;i<15;i++)
{
waveInGetErrorText(i,errormsg,256);
cout<<i<<"番:"<<errormsg<<endl;
}
cin>>tmp;
return 0;
}
コンソール出力ですが,VC6でこのまま動くかは分かりません。
14番まで表示させています。何番まであるかはmmsystem.hをメモ帳などで見てみると確認できると思います。
回答7 (この回答は回答4に対する回答です)
- 投稿ID:A2009019738
- 投稿日時:2009/01/29 19:23
毎度、丁寧な回答有難うございます。
>WAIT_TIMEOUT = 0x0102
<−−−これは、私も皆様のご指導により確認しましたが、
何故、WAIT_TIMEOUT になるのか、理解出来ません。
下記が、それに関連したコーディングですので、コメント頂けますと
あり難いです。
(強制的にエラーを起こしている理由: スレッドの終了の確認をしています)
説明が十分でないかも知れませんが、御免なさい
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
このメッセージがでる原因は、スレッド(pthreadR)の終了の前に、下記の如く
MessageBoxを実行させている為です。
(即ち、スレッドルーチンの最後で)。
スレッドルーチン{
−−−−
−−−−
GetErrorMessage(5); //この中にmessegeBoxがメッセージを表示します。
} //スレッドルーチンの最後
上記でmessegeBoxがメッセージを出さなければ(即ち、GetErrorMessage(5をコメント化する)
エラー258にはなりません。
メインルーチンの下記のコーディングで、スレッド(pthreadR)終了処理をしています。
//pthreadRの終了
if(pthreadR){
hThread=pthreadR->m_hThread;
ret=WaitForSingleObject(hThread, INFINITEX); <−−−無限待ですが、ret=258となります
if(ret) GetErrorMessage(10);
}
Q2:INFINITEXを指定していますので、無限待ちしていると思いますが、タイムアウトしている
様です。この件に関してコメント頂きますとあり難いです
Q3:スレッドの終了を遅らせるために挿入したルーチンの
一部であるmessegeBoxのメッセージに応答しる前に、スレッドは終了
すろものでしょうか?
Q2,Q3の見解を頂き、再度プログラムをcheckしたく思っています。
多分、どこか私の勘違いがあると思いますが.....
(プログラムの追加理由: スレッドの終了の確認をしています)
回答8 (この回答は回答7に対する回答です)
- 投稿ID:A2009019747
- 投稿日時:2009/01/29 19:41
>Q2:INFINITEXを指定していますので、無限待ちしていると思いますが...
INFINITEXって何ですか?
INFINITEですよ?
もうひとつpthreadRはなに?
CWinThread(及び、その継承クラス)であれば、m_bAutoDeleteにFALSEを入れておかない限り、
>hThread=pthreadR->m_hThread;
>ret=WaitForSingleObject(hThread, INFINITEX);
の、処理はThreadが終了した時点でhThreadが無効になるため不正な処理になります。
このやり方をするのであれば、代入(hThread=pthreadR->m_hThread;)ではなくDuplicateHandleしてください。
(CloseHandleを忘れないように。)
>Q3:スレッドの終了を遅らせるために挿入したルーチンの...
メッセージボックスが表示されているならば、メッセージボックスを表示しているスレッドは残っています。
回答9 (この回答は回答8に対する回答です)
- 投稿ID:A2009019846
- 投稿日時:2009/01/29 21:58
毎度お世話になります。
>INFINITEXって何ですか?
INFINITEですよ?
<−−−Inetでサンプルをみてしようしました。コンパイルエラー
になりませんでしたので、無限待ちと思っていました。
>もうひとつpthreadRはなに?
CWinThread(及び、その継承クラス)であれば、m_bAutoDeleteにFALSEを入れて
おかない限り、
<−−−−下記のA,B、Cの関係にあります。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
CWinThread* pthreadR; //konnomama <−−−A
void threadR(msr_MODE op){ <−−−−B
SW_S=0;
stop_thread_flag=0;
if(!pthreadR){
pthreadR=AfxBeginThread(test1, (void*)op, THREAD_PRIORITY_TIME_CRITICAL, 0, 0);
}
}
UINT test1(void *pvoid){ <−−−−C
ーーーーー
ーーーーー
if(ret) GetErrorMessage(3);
ret=WaitForSingleObject(hEventR, INFINITEX);
if(ret) GetErrorMessage(4);
// GetErrorMessage(5); <−−−これはtestの為に追加しました。
return 0;
}
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
>>ret=WaitForSingleObject(hThread, INFINITEX);
の、処理はThreadが終了した時点でhThreadが無効になるため不正な処理になります。
<−−−私も最初はその様に思いましたが、つい変なことをして閉まったようです。
その理由は、スレッドの終了を確認し、新規に同じスレッドを立ち上げる処理を
する為でした。
まったく、勉強不足ですが、出来ればスレッド等について宜しくお願いします。
QA:メインルーチンからスレッドの終了の確認はどの様にすればよろしいでしょうか?
回答14 (この回答は回答9に対する回答です)
- 投稿ID:A2009020230
- 投稿日時:2009/01/30 13:06
よくやるNGです。
http://msdn.microsoft.com/ja-jp/library/2s21xzfe(VS.80).aspx
「スレッドの終了コードの取得」を参照
終了時にオブジェクトが自動削除されるので参照できなくなります。
終了を待ちの1例ならば
// スレッド起動
pthreadR = AfxBeginThread(test1, (void*)op, THREAD_PRIORITY_TIME_CRITICAL, 0, CREATE_SUSPENDED);
ASSERT(pthreadR != NULL);
pthreadR->m_bAutoDelete = FALSE;
pthreadR->ResumeThread();
〜〜〜〜〜〜〜〜〜
// 終了待ち
const DWORD dwTimeout = 5000; // 5秒で終了しなかったら強制終了する
switch (WaitForSingleObject(pthreadR->m_hThread, dwTimeout)) {
default:
case WAIT_ABANDONED:
// 異常(想定外の戻り値)
ASSERT(0);
break;
case WAIT_OBJECT_0:
// 正常終了
break;
case WAIT_TIMEOUT:
// 正しく終了しないので強制終了する
TerminateThread(pthreadR->m_hThread);
break;
}
delete pthreadR;
pthreadR = NULL;
とかでしょうか?
(終了を要求するロジックは入ってませんし、自分ではこんなテキトーなコードを使うことも無いですが)
MU39氏へ
>WaitForSingleObjectなどのwin32APIも使用していますが,MFCのクラスで統一した方が問題が少なくなる...
MFCがWin32API一部をラッピングしたラッパーなので、MFCで用意されていない部分をAPIと併用するのは普通です。
>INFINITEXではコンパイラを通らないので...このMFCとwin32APIの混在が原因の一つかもしれません...
MFCでもINFINITEXは定義されていません。
どこかで#define INFINITEX 0とか宣言されているのかと。(0だから即座にタイムアウト)
(感想分)
>小生は,できるだけマルチスレッドを使わないで同じ事が実現
私は必要ならスレッドをじゃんじゃん使います。
(無駄にスレッドを作るのはダメだと思いますが、スレッドで行うことに意味があるならスレッドにしない理由はありません。)
バックグラウンドで処理しないといけないものをUIスレッドで行ってろくなことにはなりません。
回答10 (この回答は回答4に対する回答です)
- 投稿ID:A2009019860
- 投稿日時:2009/01/29 22:18
毎度お世話になります。
>WAIT_TIMEOUT = 0x0102
<−−−このエラーメッセージの表示は皆さんのおかで、正しい事がわかりました。
(その前に、私の勘違いがあったようです)
>ついでに,waveInのエラーメッセージですが,次のような感じで表示してみたらいかがですか。
<−−−エラーメッセージの獲得は、下記のルーチンで行うようにしました。
引数nは、エラー発生場所の情報です。
ーーーーーーーーーーーーーーーーーーーーーー
void GetErrorMessage(int n){
LPVOID lpMessageBuffer;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // デフォルト ユーザー言語
(LPTSTR) &lpMessageBuffer,
0,
NULL );
switch(n){ <−−−エラー発生場所の情報
case 1:
case 2:
case 3:
case 4:
MessageBox(NULL, (const char*)lpMessageBuffer, "while(1) at Test1", MB_OK);
break;
}
気が付いた点がありましたら、どうかお教えください。
回答11 (この回答は回答10に対する回答です)
- 投稿ID:A2009019897
- 投稿日時:2009/01/29 23:17
小生がアドバイスできるレベルを超えていますので参考にもならないでしょうが,思いついた点を書いておきます。
・ご提示のコードは断片的なので,よく分かりませんが,AfxBeginThreadとMFCでスレッドを作成し,イベントでスレッドを制御しているようであり,WaitForSingleObjectなどのwin32APIも使用していますが,MFCのクラスで統一した方が問題が少なくなるのではないでしょうか。
ただ,小生はMFCはほとんど分かりませんので,別に問題ないかもしれませんが。
次のマイクロソフトの解説は,分かりやすくはありませんが,一応,まとまった説明です。
http://msdn.microsoft.com/ja-jp/library/172d2hhw(VS.80).aspx
・INFINITEXではコンパイラを通らないので,実際にはINFINITEだったと思いますが,にもかかわらず,タイムアウトで戻ってくるのは,このMFCとwin32APIの混在が原因の一つかもしれません(単なる推測です。コードがいろいろ変わっており,WaitForSingleObjectの場所もコードにより異なっているので,なんだか小生も分かりません)。
・GetErrorMessageは,何を行っているのか,いまいち理解できていません。
とにもかくにも,マルチスレッドの処理は難しいので大変ですね。小生は,できるだけマルチスレッドを使わないで同じ事が実現できないかを考えてしまいます。
回答12 (この回答は回答11に対する回答です)
- 投稿ID:A2009020102
- 投稿日時:2009/01/30 10:35
毎度丁寧な回答有難うございます。
>・INFINITEXではコンパイラを通らないので,実際にはINFINITEだったと思いますが,
<−−−−下記の如く、INFINITEXでコンパイラーを通ています。
INFINITEXはスレッドの終了をcheckする時には、全てINFINITEXを使用しています。
但しそれが適正か否かは不明ですので、INFINITEに変更してcheckして見ます。
if(pthreadR){
hThread=pthreadR->m_hThread;
ret=WaitForSingleObject(hThread, INFINITEX);
if(ret) GetErrorMessage(10); //**********
}
>GetErrorMessageは,何を行っているのか,いまいち理解できていません。
<−−−その使用方法とサブルーチンの内容は下記の通りであり、
1)の使用例では、waveOutCloseが返すエラーコードを、文章に変換するものと思います。
2)のサブルーチンの内容は、私も解りませんが、結果的には正しいエラーコードに対応する
メッセージを返しています。
1)使用例
if(hwo) ret=waveOutClose(hwo);
if(ret) GetErrorMessage(12); //**********
2)サブルーチンの内容
void GetErrorMessage(int n){
LPVOID lpMessageBuffer;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // デフォルト ユーザー言語
(LPTSTR) &lpMessageBuffer,
0,
NULL );
switch(n){
case 1:
case 2:
case 3:
case 4:
MessageBox(NULL, (const char*)lpMessageBuffer, "while(1) at Test1", MB_OK);
break;
}
気が付いた点があれば、ご連絡をお待ちしております。
回答13 (この回答は回答12に対する回答です)
- 投稿ID:A2009020167
- 投稿日時:2009/01/30 11:46
12/
>>・INFINITEXではコンパイラを通らないので,実際にはINFINITEだったと思いますが,
><−−−−下記の如く、INFINITEXでコンパイラーを通ています。
といわれても、
タイトル通り「VC++6.0」なら「INFINITEX」などという宣言(予約語)は存在しません。
> 1)の使用例では、waveOutCloseが返すエラーコードを、文章に変換するものと思います。
> 2)のサブルーチンの内容は、私も解りませんが、結果的には正しいエラーコードに対応する
> メッセージを返しています。
って……
http://support.microsoft.com/kb/94999/ja
あたりからパクってきたソースですか?
それとも、よその場所ですか?
自分で創ったものなら「思います」って表示はおかしいでしょ。
それと、「VC」のエラー表示でなく「独自のエラーの内容表示」なら前回の質問は全く意味をなしていないし……
ま、個人的には
>GetErrorMessage(12);
なのに、caseが1〜4までしかないことと、defaultがない時点でおかしいと思うけど。
という以前に、「直値」使用してる時点で「汎用化」も「効率化」も一切考慮していない、今までの質問と同様「内容を理解せずに行きあたりばったりで作ってる」感が出てると思う。
分からない場合は、いろいろと検索して調べて「参考にする」のは当然として、それを「理解しないまま無理やり組み込んでる」ってところを直した方がいいと思いますがどうですか?
というようなことは、過去の質問回答にも何度かありましたね。
回答15 (この回答は回答13に対する回答です)
- 投稿ID:A2009020233
- 投稿日時:2009/01/30 13:11
>なのに、caseが1〜4までしかないことと、defaultがない時点でおかしいと思うけど。
たぶん後ろ欠けてるでしょ?
FORMAT_MESSAGE_ALLOCATE_BUFFER
使ってるのに開放が無いし。
>いろいろと検索して調べて「参考にする」のは当然として、それを「理解しないまま無理やり組み込んでる」ってところを直した方がいいと思いますがどうですか?
激しく同意。
流用するのはわかるが、内容を理解せずにこぴぺったんしてるだけなら、まともなものは一生作れない。
回答16 (この回答は回答15に対する回答です)
- 投稿ID:A2009020334
- 投稿日時:2009/01/30 15:24
毎度お世話になります。
>FORMAT_MESSAGE_ALLOCATE_BUFFER 使ってるのに開放が無いし。
<−−−上記は、バッファーの種類を明示している訳であり、その種のバッファーが
FormatMessage()なるサブルーチンの中で、取られ、 FormatMessage()が
終了する時に自動開放されるのではないでしょうか?
AppでFORMAT_MESSAGE_ALLOCATE_BUFFERの名称のバッファーを確保
したことは、ありません。
コメント、ご指導頂けますと大変光栄です。
回答17 (この回答は回答16に対する回答です)
- 投稿ID:A2009020372
- 投稿日時:2009/01/30 16:08
回答12に
>FormatMessage(
> FORMAT_MESSAGE_ALLOCATE_BUFFER |
って記載してるやん。
>FormatMessage()が終了する時に自動開放されるのではないでしょうか?
されない。
MSDN LibraryなどでFormatMessageの仕様を確認してください。
回答18 (この回答は回答17に対する回答です)
- 投稿ID:A2009020595
- 投稿日時:2009/01/30 22:19
毎度お世話になります。
貴方の回答8、回答14は、貴重な情報です。
少しは、理解して、対応(プログラムの修正)したいと思います。
>>FormatMessage()が終了する時に自動開放されるのではないでしょうか?
されない。
MSDN LibraryなどでFormatMessageの仕様を確認してください。
<−−−出来れば、どの様に記述したらよいか、教えて頂けないでしょうか?
追伸:
御免なさい。INFINITEXがdefine文で1000となっていました。
頭が、耄碌していました
今後とも宜しくお願いします。
回答19 (この回答は回答18に対する回答です)
- 投稿ID:A2009020695
- 投稿日時:2009/01/31 01:20
回答20 (この回答は回答18に対する回答です)
- 投稿ID:A2009020857
- 投稿日時:2009/01/31 09:59
18/
>少しは、理解して、対応(プログラムの修正)したいと思います。
「少し」じゃない「全部」理解する!
>MSDN LibraryなどでFormatMessageの仕様を確認してください。
><−−−出来れば、どの様に記述したらよいか、教えて頂けないでしょうか
今まで指摘されたことは一切無視ですか?
少しは自分で考えよう(調べる/実験ソースを組む)という気はないのですか?
>御免なさい。INFINITEXがdefine文で1000となっていました。
>頭が、耄碌していました
そういう以前の問題。
複数の方が「ない」と言ってるのに、「コンパイルが通っているから」と一切定義のチェックもしなかった時点でおかしいです。
穿った事を言えば、「文法(コンパイル)エラーはないから、正常に動くはずだ」と決めつけている。
あたりまえだけど『論理エラー』については一切考えていない時点で「プログラマー」として根本的なことが抜けおちている。
>今後とも宜しくお願いします。
あなた個人に対してはっきり言えば「嫌です」。
自分の技術を向上させようという意欲ゼロかマイナスですか?
しかしながら、ここは不特定多数の利用する場であり、変な単語で検索して誤ったソースを誰かさんのように『理解せずにそのまま使用』したりされると困りますので、問題箇所の指摘だけはするかもしれません。
過去の回答者が貴方に対して表現を荒げていく理由がよーーーーーーーーーーーーーくわかりました。