みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

VC++スレッドの正しい終了のさせかた

VC++6.0にてAfxBeginThreadで
m_bAutoDelete = TRUEにてスレッドをおこしております。
この終了時に制御関数のwhileループを脱する様にし、
正常にスレッドを終了させているつもりです。
この後、再度(アプリは継続して起動したまま)
AfxBeginThreadにて全く同じ処理で再開すると、
なぜか、前のスレッドが未だ動作しているかのごとく
制御関数内のTRACEが2重に出力されます。
再度、停止し、またスレッド起動すると、
今度は3重になったかの様な動作をします。

スレッドが正しく終了されていないのでは?と思った現象として、
1回起動時にアプリを終了させると正常終了しますが、
2回起動以上は必ずスレッドのメモリーリークが出ます。
メモリーリーク個所はAfxBeginThreadでした。

制御関数内で必要ないとは思いましたが、終了時に
AfxEndThreadを使用しましたが現象は同じでした。

そこで質問です。
1)この現象は、スレッドが正常に終了されていない事に起因しているのでしょうか?
2)スレッドを正しく終了させるにはどうすればいいのでしょうか?
当方、制御関数がループを抜け、さらにm_bAutoDelete = TRUEであれば
オブジェクトも自動的に破棄されると思っていたのですが。。。

以上、よろしくお願いします。

投稿日時 - 2008-11-27 01:26:11

QNo.4510338

すぐに回答ほしいです

質問者が選んだベストアンサー

 こんばんは。
 AfxEndThread()で起動した物は「m_pThread->PostThreadMessage(WM_QUIT, 0, 0)」で終了させないといけないらしいです。
 http://hp.vector.co.jp/authors/VA014436/prg_memo/windows/vctips/038.html

 試してみましたが、此れで一応綺麗に終るようです。

CWinThread* m_pThread;
bool m_bSuspend = false;

static UINT Proc(LPVOID pData)
{
MSG msg;
CDlg* p = static_cast<CDlg*>(pData);

p->SetDlgItemText(IDC_EDIT1, "START");

while(::GetMessage(&msg, NULL, 0, 0))
{
switch(msg.message)
{
//case WM_QUIT:break;
default:;
}
}
//ココまで来ないといけない
p->SetDlgItemText(IDC_EDIT1, "END");

return 0;
}

void CDlg::OnSwitch()
{
// TODO: この位置にその他の検証用のコードを追加してください
//初めての作成
if(!m_pThread)
{
m_pThread = ::AfxBeginThread(&::Proc, this);
}
else
{
//寝ているスレッドを叩き起こす
if(m_bSuspend)
{
SetDlgItemText(IDC_EDIT1, "RESUME");
m_pThread->ResumeThread();
}
//寝かす
else
{
SetDlgItemText(IDC_EDIT1, "SUSPEND");
m_pThread->SuspendThread();
}

m_bSuspend ^= true;
}
}

void CDlg::OnExit()
{
// TODO: この位置に特別な後処理を追加してください。
if(m_pThread)
{
//寝ているスレッドを叩き起こす(寝ていなければ無視される)
m_pThread->ResumeThread();
m_pThread->PostThreadMessage(WM_QUIT, 0, 0);
m_pThread = 0;
}
}

投稿日時 - 2008-11-27 18:58:33

お礼

回答ありがとうございました。
原因は、制御関数内のwhile文を抜ける前に次のスレッドが起動されて
いる様で、そこで前のスレッドが正しく終了していませんでした。
スレッド停止命令後にwaitforsingleobjectにて待機させ、制御関数内のwhile文を抜けた後にseteventする処理手順を踏んだらOKでした。
ありがとうございました。
あと、PostThreadMessage(WM_QUIT, 0, 0)も試してみました。ばっちりでした。勉強になりました。

投稿日時 - 2008-11-30 18:09:55

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

>1)この現象は、スレッドが正常に終了されていない事に起因しているのでしょうか?
はい。

>2)スレッドを正しく終了させるにはどうすればいいのでしょうか?
>当方、制御関数がループを抜け、さらにm_bAutoDelete = TRUEであれば
>オブジェクトも自動的に破棄されると思っていたのですが。。。
「オブジェクトの破棄」と「オブジェクト内で生成したオブシェクトの破棄」はイコールではありません。
AfxBeginThreadで生成しているスレッド内で作成、もしくは実行しているオブジェクトの終了ミスか、
終了処理は行っていても、スレッド終了時までにその処理が間に合わず残っている可能性はあります。

投稿日時 - 2008-11-27 10:05:09

お礼

回答ありがとうございました。
原因は、制御関数内のwhile文を抜ける前に次のスレッドが起動されて
いる様で、そこで前のスレッドが正しく終了していませんでした。
スレッド停止命令後にwaitforsingleobjectにて待機させ、制御関数内のwhile文を抜けた後にseteventする処理手順を踏んだらOKでした。
ありがとうございました。

投稿日時 - 2008-11-30 18:08:44

あなたにオススメの質問