c++ builder / TThread > スレッドが終了時にソフトを終了する実装


動作確認
C++ Builder XE4

メインスレッドがエラーで終了した時にソフトを終了させる実装を考えた。

Main.cpp

Main.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    m_terminate = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
    String msg = DateTimeToStr(Now());
    OutputDebugString(msg.c_str());

    if (m_terminate) {
        Close();
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
    m_thr_main = new TThreadMain(/* CreateSuspend=*/false);
}
//---------------------------------------------------------------------------

__fastcall TForm1::~TForm1()
{
    if (m_thr_main != NULL) {
        m_thr_main->Terminate();
        for(int idx=0; idx<5; idx++) {
            Sleep(200);
            Application->ProcessMessages();
        }
    }
}

void __fastcall TForm1::SetTerminate()
{
    m_terminate = true;
}

Main.h

Main.h
//---------------------------------------------------------------------------

#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include "ThreadMain.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE で管理されるコンポーネント
    TTimer *Timer1;
    void __fastcall Timer1Timer(TObject *Sender);
    void __fastcall FormShow(TObject *Sender);
private:    // ユーザー宣言
    bool m_terminate;
    TThreadMain *m_thr_main;
public:     // ユーザー宣言
    void __fastcall SetTerminate();

    __fastcall TForm1(TComponent* Owner);
    __fastcall ~TForm1();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

ThreadMain.cpp

ThreadMain.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "ThreadMain.h"
#include "Main.h"

#pragma package(smart_init)
//---------------------------------------------------------------------------

//   重要: VCL におけるオブジェクトのメソッドとプロパティは、Synchronize を使って
//   呼び出されるメソッドでのみ使用できます。たとえば、次のようになります。
//
//      Synchronize(&UpdateCaption);
//
//   ここで、UpdateCaption は 次のようなコードになります。
//
//      void __fastcall TThreadMain::UpdateCaption()
//      {
//        Form1->Caption = "スレッドで更新されました";
//      }
//---------------------------------------------------------------------------

__fastcall TThreadMain::TThreadMain(bool CreateSuspended)
    : TThread(CreateSuspended)
{
    FreeOnTerminate = true;

}
//---------------------------------------------------------------------------
void __fastcall TThreadMain::Execute()
{
    for(int idx = 0; idx < 5; idx++) {
        Sleep(1000);
    }

    Form1->SetTerminate();

    String msg = L"finish Execute()";
    OutputDebugString(msg.c_str());
}
//---------------------------------------------------------------------------

ThreadMain.h

ThreadMain.h
//---------------------------------------------------------------------------

#ifndef ThreadMainH
#define ThreadMainH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
//---------------------------------------------------------------------------
class TThreadMain : public TThread
{
private:
protected:
    void __fastcall Execute();
public:
    __fastcall TThreadMain(bool CreateSuspended);
};
//---------------------------------------------------------------------------
#endif

スレッドがExecute()を抜ける時にForm1のSetTerminate()をコールするようにした。

スレッドがForm1に依存してしまう。
closureを使うのも手かもしれない。

スレッドが落ちた時にソフトを終了でなく、スレッドを再起動することもできそう。