マルチスレッドの強制終了 – プログラミング – Home

マルチスレッドの強制終了
 
通知
すべてクリア

[解決済] マルチスレッドの強制終了

固定ページ 1 / 2

にし
 にし
(@にし)
ゲスト
結合: 23年前
投稿: 22
Topic starter  

毎度お世話になります。

今、VC++6のMFCでマルチスレッドプログラム作成の準備として
簡単なモデルプログラム(下記)を作っています。
モデルプログラムは、ワーカースレッドのカウントUPをEditBoxに表示する簡単なもの
ですが、スレッド動作中にスレッドを強制終了(OnDestroy)させると
メモリリークが発生します。

Detected memory leaks!
Dumping objects ->
thrdcore.cpp(166) : {63} client block at 0x00374688, subtype 0, 112 bytes long.
a CWinThread object at $00374688, 112 bytes long
Object dump complete.

スレッド動作を一旦中断(OnThreadCan)させてから中止(OnDestroy) させれば
メモリリークは起きません。何か気付いた所がありましたらお願いします。

//----- モデルプログラムの一部

UINT ThreadProc(LPVOID pParam);
CEvent m_pTermThreadsEvent;

//----------スレッド開始-------------------------

void CThreadDlg::OnThread()
{
AfxBeginThread(ThreadProc,GetSafeHwnd());
}

//---------スレッド中断--------------------------

void CThreadDlg::OnThreadCan()
{
m_pTermThreadsEvent.SetEvent(); //停止信号をThreadProcに送る
}

//---------スレッド------------------------------

UINT ThreadProc(LPVOID pParam)
{
int sum = 0;

for (int i = 0; i < 300; i++) {
Sleep(20); //動作遅延
sum++; //加算
SetDlgItemInt((HWND)pParam, IDC_EDIT1, UINT(sum), TRUE); //加算表示
//停止信号チェック
if(::WaitForSingleObject(m_pTermThreadsEvent, 0) == WAIT_OBJECT_0) {
AfxEndThread(0);
break;
}
}
return 0;
}

//-----------スレッド中止-----------------------

void CThreadDlg::OnDestroy()
{
CDialog::OnDestroy();

m_pTermThreadsEvent.SetEvent();  //停止信号をThreadProcに送る
WaitForSingleObject(m_pTermThreadsEvent, INFINITE); //スレッド終了待ち
}


引用未解決
トピックタグ
TAD
 TAD
(@TAD)
ゲスト
結合: 23年前
投稿: 54
 

OnDestroy で、基本クラスを呼び出す前に、スレッドの終了待ちをしてみてはどうでしょう。
または、OnDestroy ではなく、OnClose を使ってみるのもいいかもしれません。その場合、
OnOK などにもスレッド終了処理を記述する必要がありますけど。


返信引用
にし
 にし
(@にし)
ゲスト
結合: 23年前
投稿: 22
Topic starter  

TADさん 有難うございます。

>スレッドの終了待ちをしてみてはどうでしょう

OnDestroyのWaitForSingleObjectでスレッドの終了待ちをしているつもりなんですが
これでは不十分なんでしょうか。
OnCloseは試してみます。


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> WaitForSingleObject(m_pTermThreadsEvent, INFINITE); //スレッド終了待ち

これは m_pTermThreadsEvent が SetEvent されるのを待つだけに見えますが、
このような方法が可能なのでしょうか?

スレッドの終了を待つときは、スレッドハンドルに対してWaitします。


返信引用
Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
 

Puppyです。 dairygoodsさん おはようございます。

>スレッドの終了を待つときは、スレッドハンドルに対してWaitします。

そうしないと、いけないんでしょうか?

Puppyもワーカスレッド内でEventオブジェクトをWaitForSingleObjectで
待機しているんですけどぉ。何か問題が起きますか?

よろしくお願いします。m(..)mぺこり


返信引用
TAD
 TAD
(@TAD)
ゲスト
結合: 23年前
投稿: 54
 

CEvent の基本クラス、CSyncObject の変換演算子によって、HANDLE 値が返されるようです。
コンパイル時にエラーや警告が起こっていないのなら、問題ないと思いますが、HANDLE 型にキャ
ストすれば確実でしょう。


返信引用
Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
 

Puppyです。 TADさん お返事ありがとうございます。

にしさん 横から、入ってきてごめんなさい。

>コンパイル時にエラーや警告が起こっていないのなら、問題ないと思いますが、HANDLE
>型にキャストすれば確実でしょう。

CreateEvent APIでイベントオブジェクトを作成してます。
そのイベントオブジェクトのHANDLEをWaitForSingleObjectで待ってます。

問題ないでしょうか?m(..)mぺこり


返信引用
にし
 にし
(@にし)
ゲスト
結合: 23年前
投稿: 22
Topic starter  

dairygoodsさん、 Puppyさん、 TADさん 有難うございます。

>スレッドの終了を待つときは、スレッドハンドルに対してWaitします。

確かに、WaitForSingleObjectのHelpをみると「オブジェクトのハンドルを指定します」
とかいてあるので、ハンドルの指定かと思ったのですが、AfxBeginThreadの戻り値は
ポインタなのと、各サイトのQ&Aを見るとこの方式が結構使われているようなので
使用したわけです。

>コンパイル時にエラーや警告が起こっていないのなら
コンパイルではエラーは起きていません。

>HANDLE 型にキャストすれば確実でしょう。
はなはだ申し訳ありませんが、何処をどうゆふうにCASTすればいいのか
ヒントだけでもいただけないでしょうか?


返信引用
TAD
 TAD
(@TAD)
ゲスト
結合: 23年前
投稿: 54
 

Puppyさん>

Puppy さんも、スレッドの終了処理ですか? それなら、ワーカースレッドで待機するのでは
なく、主スレッドで待機するべきではないでしょうか。主スレッドで、ワーカースレッドの終了を
待機、確認してから、主スレッドの終了処理を行います。
CreateEvent で作成したハンドルを指定しているは、間違っていませんよ。

にしさん>

キャストは普通のキャストと同じです。

WaitForSingleObject((HANDLE)m_pTermThreadsEvent, INFINITE);

とするだけです。

しかし、先ほども言いましたが、やらなくても問題はないはずです。
この位置にブレークポイントを設定して止めてから、ステップイン(F11)してみると、
operator HANDLE() が呼ばれているのが確認できると思います。

CEvent はイベントオブジェクトをカプセル化しただけのもので、コンストラクタで API の
CreateEvent が呼ばれています。


返信引用
Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
 

Puppyです。

WaitForSingleObject((HANDLE)m_pTermThreadsEvent, INFINITE); //スレッド終了待ち

こーゆーことでしょうか?
違ってたら、ごめんなさい。m(..)mぺこり


返信引用
Puppy
 Puppy
(@Puppy)
ゲスト
結合: 23年前
投稿: 71
 

Puppyです。 TADさん お返事ありがとうございます。

>Puppy さんも、スレッドの終了処理ですか? 

はい。

>それなら、ワーカースレッドで待機するのでは
>なく、主スレッドで待機するべきではないでしょうか。
>主スレッドで、ワーカースレッドの終了を
>待機、確認してから、主スレッドの終了処理を行います。

そうなんですか。よくわかっていないので。。。
どこかに例題ありませんか。
もうすこしよく勉強して、出直しますぅ。m(..)m


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> 確かに、WaitForSingleObjectのHelpをみると「オブジェクトのハンドルを指定します」
> とかいてあるので、ハンドルの指定かと思ったのですが、AfxBeginThreadの戻り値は
> ポインタなのと、各サイトのQ&Aを見るとこの方式が結構使われているようなので
> 使用したわけです。

すみません、ハンドルかポインタかと言うことではなく、
最初のコードを見る限り、m_pTermThreadsEvent は、AfxBeginThread の
戻り値ではなく、単なる CEvent ですよね。

スレッドの終了を待つのであれば、

CWinThread* pThread = AfxBeginThread(...);
...
::WaitForSingleObject(*pThread, INFINITE);

としなければならないと思います。


返信引用
TAD
 TAD
(@TAD)
ゲスト
結合: 23年前
投稿: 54
 

マルチスレッドを使った、過去の自分のソースを見てみました。
MFC ではなく API だったのですが、イベントオブジェクトを作ることなく、CreateThread で得
たスレッドハンドルを WaitForSingleObject に渡して終了待ちをしていました。
とすると、dairygoods さんの示してくれたコードでいけそうです。
dairygoods さん、ご指摘ありがとうございました。


返信引用
TAD
 TAD
(@TAD)
ゲスト
結合: 23年前
投稿: 54
 

追加です。

>m_pTermThreadsEvent.SetEvent();  //停止信号をThreadProcに送る
>WaitForSingleObject(m_pTermThreadsEvent, INFINITE); //スレッド終了待ち

これだと確かにおかしいですね。

SetEvent でシグナル状態にしているのですから、次の WaitForSingleObject は無意味になっ
てしまいます。ここをスレッドのハンドルに変えれば正しく動作するはずです。

うーん、どうして最初に気が付かなかったんだろう。


返信引用
Bun
 Bun
(@Bun)
ゲスト
結合: 24年前
投稿: 761
 

>>m_pTermThreadsEvent.SetEvent();  //停止信号をThreadProcに送る
>>WaitForSingleObject(m_pTermThreadsEvent, INFINITE); //スレッド終了待ち
>これだと確かにおかしいですね。

おかしいでしょうか?

元発言を見ると、問題ないように思えますけど。

SetEventすることによって、スレッド終了のトリガをかけているのではないでしょうか?

INFINITE とすべきではないと思いますが。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました