タイトルをより適切に変更しました
###前提・実現したいこと
MFCアプリケーションを閉じる動作を行う際、コントロールが参照不能になる前に処理を行いたい。
~~ 閉じる動作を行う際にコントロールが参照不能になる以前の状態で処理を行えるイベントが知りたい。~~
閉じる動作を行う際にコントロールが参照不能になる現象を解消、または回避したい。
- 作成中のアプリケーションはダイアログベースのMFCアプリケーションです。
- OnDestroy()イベント関数内で、CDialog::OnDestroy()が走る前にGetExitCodeThread()で別スレッドの終了コードを取得して別スレッドの終了を確認してからアプリケーションを終了する処理を実装しようとしています。
- 別スレッドは1つです。
- 別スレッド内ではループで処理を行い、その中ではメインスレッドのコントロールの値を参照しています。
- メインスレッドではGetExitCodeThread()を実行する前に別スレッドのループを終わらせるフラグを立てて、別スレッドが終了したときにGetExitCodeThread()でexitCode = 0 となるようにしいます。
- OnDestroy()を使用しているのはブレークポイントを設置して観察して、OnClose()や~CMyAppDlg()よりも早く実行されることを確認したためです。
実際のソースコードを提示できないため抽象的な質問になり申し訳ありませんが、アドバイスなど頂けたら幸いです。
よろしくお願いいたします。
###発生している問題・エラーメッセージ
OnDestory()に処理が移って別スレッドのループ終了フラグがtrueになったあと
別スレッドが最後のループに入ったときに、スライドコントロールの位置を参照しようと( CSliderCtrl::GetPos() )すると
エラーメッセージが出るわけでも突然プロセスが終了するわけでもなく、GetExitCodeThread()の値を監視しているループから抜けられずアプリケーションが終了しなくなってしまいます。
別スレッドではCSliderCtrl::GetPos()の処理に入ってから処理が進まなくなります。
###該当のソースコード
このサイトなどを参照するとOnDestroy()より先にOnClose()が走るようなので修正しました。
OnDestroy内に記述でもよいとのご指摘があったので元に戻し、ご指摘のあった部分を修正しました。
c++
1void CMyAppDlg::OnDestroy() 2{ 3 // デストロイする前にカメラスレッドを終了させる 4 WaitForSingleObject( this->m_mutex, 0); 5 this->m_exitFlagAnotherThd = true; 6 ReleaseMutex( this->m_mutex); 7 8 DWORD exitCode = -1; 9 do{ 10 // this->m_hAnotherThread は ResumeThread( this->m_hAnotherThread);によって開始済みのスレッド 11 if( !GetExitCodeThread( this->m_hAnotherThread, &exitCode)) 12 { 13 TerminateThread( this->m_hAnotherThread, E_FAIL); 14 break; 15 } 16 }while( exitCode == STILL_ACTIVE); 17 // mutex 18 CloseHandle(this->m_mutex); 19 20 CDialog::OnDestroy(); 21 22 // TODO: ここにメッセージ ハンドラ コードを追加します。 23} 24// 別スレッドの実行内容 25DWORD WINAPI CMyAppDlg::ExecThread() 26{ 27 WaitForSingleObject( this->m_mutex, 0); 28 this->m_exitAnotherThd = false; // ループ終了フラグ 29 ReleaseMutex( this->m_mutex); 30 // メインループ(の代わりのWhileループ) 31 int i =0; 32 while( !this->m_exitAnotherThd){ // m_exitAnotherThd == falseになるまで待機 33 // ここから先に進まない 34 i = ((CSliderCtrl *)FromHanlde(this->m_hwnd)->GetDlgItem(IDC_SLIDER1))->GetPos(); // ウィンドウハンドラを介して取得 35 } 36 i = ((CSliderCtrl *)FromHanlde(this->m_hwnd)->GetDlgItem(IDC_SLIDER1))->GetPos(); 37 // i = ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->GetPos(); 38 return S_OK; 39}
- OnDestory()関数が呼び出されるまではiにスライダの値が正常に入ります。
以上のコードは実際に実装しているものとは異なります。雰囲気だけでも伝われば幸いです。
###補足情報(言語/FW/ツール等のバージョンなど)
VisualStudio2008 SP1
C++/MFC
Windows7/64bit SP1

回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/12/28 04:29