スレッドについて勉強中なのですが、簡単なスレッド作り、
スレッドの処理が終わってからメインの処理を行わせたくて
以下のようなプログラムを書いてみました。
そこで、WaitForSingleObjectを使ってスレッドが終了するのを
待ちたいのですが、WaitForSingleObjectではまってしまうようで
メッセージ表示が出力されません。
WRITE関数の処理が終われば、、WaitForSingleObjectで処理が
戻ってくると考えているのですが…。
スレッドについてと、間違いについて教えてもらえないでしょうか?
宜しくお願いします。
void button1()
{
if(file = INVALID_HANDLE_VALUE)
{
//一回目にボタンが押された場合は、こちら
m_file = CreateFile(...);
m_hThead = CreateThread(NULL,0,WRITE,(LPVOID)NULL,0,NULL);
m_stop = false;
}else
{
//二回目にボタンが押された場合は、こちら
m_stop = true;
::WaitForSingleObject(g_hThead, INFINITE);
CloseHandle(m_file);
CloseHandle(m_hThead);
m_file = INVALID_HANDLE_VALUE;
}
}
void WRITE()
{
while(!m_stop)
{
WriteFile(...);
}
...処理を行う
メッセージ表示(スレッドを終了します。)
}
m_hTheadとg_hTheadは同じですか?
すみません。掲示板に記入の際の書きミスです。
m_hTheadが正しいです。(つづりは間違えていますが;)
if(file = INVALID_HANDLE_VALUE)
は
if(file == INVALID_HANDLE_VALUE)
じゃない?
CreateThreadで指定するのって
DWORD WINAPI ThreadProc(
LPVOID lpParameter // スレッドのデータ
);
のはずだから
void WRITE()
は間違えでは?
m_file = CreateFile(...)の結果がINVALID_HANDLE_VALUEではないよね?
CreateThreadの結果のm_hTheadがNULLではないよね?
WaitForSingleObjectではまってたら
二回目のbutton1()でフリーズになっているはず。
スレッドからのメッセージ表示が失敗しているだけという可能性は?
>WRITE関数の処理が終われば、、WaitForSingleObjectで処理が
>戻ってくると考えているのですが…。
そのはず。
wclrp ( 'o') さんの指摘で解決されると思います。
ところで、VS2008(VS2005もかな?)の場合、
if(file = INVALID_HANDLE_VALUE) は、デフォルトの警告レベルだと
「warning C4706: 条件式の比較値は、代入の結果になっています。」
が出ないんですよね。(上記は警告レベル4で表示されます)
C++Builderの場合は既定オプションでも
「おそらく不正な代入です」みたいな警告が表示されたと思いますが。
あと、CreateThread()使用の妥当性(問題点)については
一度過去ログを参照されてみてはいかがでしょうか。
キーワードとしては
CreateThread()
_beginthread()
_beginthreadex()
AfxBeginThread()
この辺りです
1. 他に、イベント用のハンドルを用意して,CreateEventで作成する。
2. スレッドの終了時にSetEventを実行する。
3. WaitForSingleObjectは作成したイベントハンドルで待つ。
を行ってみたらどうですか?
・スレッドハンドルがおかしいのか。
・スレッド内でグルグル空回りしているのか。
わかるんじゃないかな?
既に話が進んでいますけれど、せめて使用言語と環境くらいは書いて欲しいです。
この辺の記述が全く無いのでMFCはつかっているのかとかC++なのかCなのかとか
さっぱり解りませんし。
あと、やたらとm_がついた変数があるんですが、
グローバル変数なんだったらm_はつけないほうが良いカナと。
Microsoftのソースではメンバー変数にm_がつく様になっているので
誤解されそう。
wclrp ( 'o') さん
>void WRITE()は間違えでは?
すみません。ソース上では正しいのです。
記入上のミスです。
>m_file = CreateFile(...)の結果がINVALID_HANDLE_VALUEではないよね?
>CreateThreadの結果のm_hTheadがNULLではないよね?
ではないです。
>WaitForSingleObjectではまってたら二回目のbutton1()でフリーズになっているはず。
>スレッドからのメッセージ表示が失敗しているだけという可能性は?
それも実際は、エラーチェックを行っているので問題ないです。
WaitForSingleObjectまで来て止まっているのは、確認しています。
WaitForSingleObjectをコメントにすると正常にWRITEスレッドが終了することも確認して
います。言葉足らず、記入ミスが多くてすみません。
FUKUさん
>if(file = INVALID_HANDLE_VALUE)
これも記入ミスです。急いで書いたもので、ソースをコピーしたわけでないので
間違いがいっぱいで誤解を招いてすみません。。
>CreateThread()使用の妥当性(問題点)
これは、見てみます。ありがとうございます。
通りすがりさん、瀬戸っぷさん
初めに教えて!に書いたのですが、友人に聞いたら、そこよりVCの掲示板に
書いたほうがいいよと進められ、超初心者?の方に書いたのですが。
友人に書いたと報告したらそこよりここに書いたほうがいいよと
言われて最終的にこうなってしまいました。。
4月までになんとかスレッドの理解をしたいという思い、
急いでいたこともあって、記入ミス、掲示板の複数書き込みすみませんでした。。
初めてこういう場所で質問をするので、マナーがわかっておらずすみませんでした。
「CreateFile」は通信?/ファイル?どっちで使ってますか?
通信の同期モードで使っていてとまっていませんか?
チェックしておいたほうがいいですね。
いっそうのこと、ないも処理しない(空)の状態にしてみたらどうでしょうか。
>初めてこういう場所で質問をするので、マナーがわかっておらずすみませんでした。
複数書込みした掲示板に
ここの
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200803/08030079.txt
を書いておきましょう。
できちっとここに移りました。
等のの記述も忘れずに。
ITOさん
>1. 他に、イベント用のハンドルを用意して,CreateEventで作成する。
>2. スレッドの終了時にSetEventを実行する。
>3. WaitForSingleObjectは作成したイベントハンドルで待つ。
こちらは、質問する前に試しでやってみました。
結果は同じでスレッドがどうも止まってしまっているような感じです。
WaitForSingleObjectは正常にきていて、WRITEスレッド内のWriteFileに
ブレイクをおいてもWhileを抜けたところにおいても飛んできませんでした。
WaitForSingleObjectではなくて、
//二回目にボタンが押された場合は、こちら
m_stop = true;
if(m_stop == true) // WaitForSingleObjectから変更
Sleep(100); //
CloseHandle(m_file);
CloseHandle(m_hThead);
m_file = INVALID_HANDLE_VALUE;
void WRITE()
{
while(!m_stop)
{
WriteFile(...);
}
...処理を行う
m_stop = false; // 追加
}
とすると正常に動作します。
PATIOさん
すみません、環境を書く必要があったのですね。
初めてなものでわかっておらずすみませんでした。
これはC++とCの環境両方で試しています。
なので、掲示板記入の際に、書き方が混じってしまっておりすみません。
その理由としては、C++を使用してスレッドを作成した場合、
クラスに関連付けがないため?スレッド関数からクラスのメンバーに
アクセスできないというなことを理解したくて二つ作って試してみています。
ソースコードが不正確な上に Windows のメッセージループの理解度も不明なので
どこから解説しなければならないのか微妙なのだが・・・
WaitFor*Object* を使ってよい場所と
MsgWaitForMultipleObjects* でなければならない場所と
存在する。そこで単純に WaitFor してよいかどうかを検証してあるかい?
# そーいう話まで理解しようとするなら一日程度ではすまないぜ
あと既に指摘があるけど CreateThread ではダメな場合がある
beginthread/ex や AfxBeginThread に直さなければ動かない可能性がある
worker スレッド作って、そして UI スレッドがそれを WaitFor する
ってのは原理的に無意味なので、たとえテスト目的でも違う方式取るべきだな
>ITOさん
通信かファイルというはたぶん引数のことだと思いますが
CreateFile(szFilename, GENERIC_WRITE, 0, (LPSECURITY_ATTRIBUTES) NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
こうなっています。自分的にはファイルのつもりです。
>いっそうのこと、ないも処理しない(空)の状態にしてみたらどうでしょうか。
Σなるほど!そうですね!スレッド関数とWaitForSingleObjectだけを置いて
空で試してみます!そうすればどこが悪いかわかりますね。
それは考えつきませんでした。すぐ試してみます。
複数の掲示板に書いたことを記入してきます。
ありがとうございます。