こんにちは、ワーカースレッド終了処理について教えて下さい
void CTmpView::OnRButtonDown(UINT nFlags, CPoint point)
{
// スレッド停止
// スレッド停止
if( m_pThread ) {
m_bThreadStop = TRUE;
::WaitForSingleObject(m_pThread->m_hThread, INFINITE);
m_pThread = NULL;
}
// サスペンド状態で開始
m_bThreadStop = FALSE;
m_pThread = AfxBeginThread( ::ThreadFunc, this,
THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED );
m_pThread->m_bAutoDelete = FALSE;
m_pThread->ResumeThread(); // 再開
CListView::OnRButtonDown(nFlags, point);
}
UINT ThreadFunc( LPVOID pParam )
{
CTmpView* pthis = (CTmpView *)pParam;
for( ) {
// スレッドの処理
if( pthis->m_bThreadStop ) return 0;
}
return 0;
}
スレッドの処理が終わらないうちに何回か右クリックをすると、処理が帰ってこなくなります。
WaitForSingleObjectだとは思うのですが、解決策がわかりません。
上記の記述でワーカースレッドの終了処理は正しいのでしょうか?
いろんなサイトを見て寄せ集めた記述で自信がありません。
WIN2000 SP2
VC6.0 SP5
MFC使用
よろしくお願いします
終了方法は問題ないと思います。
「スレッドの処理」側からメインスレッドに
メッセージを投げたり(たとえば、CTmpViewのCWndメソッドを呼ぶ)
していませんか?
その場合、デッドロックになります。
ところで、このソースでは、
> m_pThread->m_bAutoDelete = FALSE;
としているのに、
delete m_pThread;
が無いためメモリリークしています。
回答ありがとうございます
前回のソースは簡単にしていたので全部書きます
UINT ThreadFunc( LPVOID pParam )
{
THREAD_INFO* stThreadInfo = (THREAD_INFO *)pParam;
CListCtrl& wndList = stThreadInfo->pthis->GetListCtrl( );
CImageList* pImgList = stThreadInfo->pthis->GetImgListPtr();
CJpegBitmap* pJpegBitmap = stThreadInfo->pthis->GetJpegBitmapPtr();
CUIntArray* puiaPhotoNum = stThreadInfo->puiaNum;
CString szPath = stThreadInfo->pDoc->GetPath();
for( int i = 0; i < puiaPhotoNum->GetSize(); i++ ) {
int nPhotoNum = puiaPhotoNum->GetAt( i ) -1;
// ファイル名取得
CString szFileName = stThreadInfo->pDoc->GetPhotoData()->GetFileName(
nPhotoNum );
CString szFilePath = szPath + PHOTO_FOLDER + szFileName;
CBitmap* pBitmap = pJpegBitmap->AddBitmapEx( szFilePath );
if( pBitmap ) {
pImgList->Replace( i, pBitmap, pBitmap );
wndList.RedrawItems( i, i );
}
// m_bThreadStopがTRUEならスレッド停止
if( stThreadInfo->pthis->GetStopFlg() ) return 0;
}
return 0;
}
ッてソースです。
この場合たくさんメインスレッドにメッセージを投げているのですが、
これが原因でしょうか?
どこかのサイトで
ワーカースレッド:ウィンドウ無し
UIスレッド :ウィンドウあり
とあったのでワーカースレッド(AfxBeginThread)で作成しました。
もしかしてUIスレッド(CreateThread?)しなきゃだめですか?
もう一つデッドロックってどういう状態でしょう。
自分でも並行して調べますが、
よろしくお願いします。
ワーカースレッドの使い方は間違っていません。
こちらを参照してください。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200206/02060070.txt
右クリックを押して、スレッドが終了した後で、
そのスレッド内で投げ込んだ描画処理が行われているとか。
回答ありがとうございます。
while (WaitForSingleObject(m_pThread->m_hThread, 0)==WAIT_TIMEOUT) {
MSG msg;
if (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) {
AfxGetApp()->PumpMessage();
}
}
を利用してうまくいきました。
メッセージポンプ?ループとか言うやつですよね。
大変参考になりました。ありがとうございます。
> を利用してうまくいきました。
> メッセージポンプ?ループとか言うやつですよね。
この場合、スレッドを待っている間も右クリックを処理して
しまうことに注意してください。
つまり、OnRButtonDown()のwhile文内でループしている間に、
右クリックすると再度OnRButtonDown()が呼び出されます。
ありがとうございます。
実際のソースは右クリックではなく、ツリービューのSelectItemから発生する関数です。
嘘を書いたのではありません。右クリックのイベントの方が直感的なのでそのようにしました。
ツリービューのSelectItemなので、同じ所でクリックしてもイベントが発生しない為、
ご指摘の症状はでませんでした。
ツリービューのSelectItemの最初にTRACE文を書いて確認しました。
TRACE文は実行されませんでした。
右クリックのようなイベントの時は気をつけます。フラグで何とかなるのかな?
貴重な御意見ありがとうございます。