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

```txt:動作確認
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を使うのも手かもしれない。

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