Your ThreadTerminateIfDone()
function needs to take the thread pointer by reference, otherwise it will not be able to set pointer to NULL correctly:
void __fastcall TForm1::ThreadTerminateIfDone(TMyThread* &T)
With that said, you can eliminate ThreadTerminateIfDone()
altogether if you use the thread's OnTerminate
event to keep track of whether the thread is running. When FreeOnTerminate
is set to true, OnTerminate
is triggered before the thread is freed, eg:
class TMyThread : public TThread
{
private:
String StatusLine; // Used for Synchronize function
void __fastcall UpdateGUI();
protected:
virtual void __fastcall Execute();
public:
__fastcall TMyThread();
};
//------------------------------------------------------------------------------
extern TMyThread *MyThread;
//------------------------------------------------------------------------------
.
TMyThread *MyThread = NULL;
__fastcall TMyThread::TMyThread()
: TThread(true)
{
FreeOnTerminate = true;
Priority = tpNormal;
}
void __fastcall TMyThread::UpdateGUI()
{
Form1->Label1 = StatusLine;
}
void __fastcall TMyThread::Execute()
{
Sleep(2000);
StatusLine = "I am almost done!";
Synchronize(&UpdateGUI);
}
void __fastcall TForm1::StartOrRestartThread(TObject *Sender)
{
if (MyThread == NULL)
{
MyThread = new TMyThread();
MyThread->OnTerminate = ThreadTerminated;
MyThread->Start();
}
else
{
Application->MessageBox(L"Thread is still running please wait!", L"Error", MB_OK);
}
}
void __fastcall TForm1::ThreadTerminated(TObject *Sender)
{
MyThread = NULL;
}
To answer your other question, if you want the thread to be restartable then you have to change the thread design a bit, eg:
class TMyThread : public TThread
{
private:
String StatusLine; // Used for Synchronize function
TEvent *RestartEvent;
void __fastcall UpdateGUI();
protected:
virtual void __fastcall Execute();
public:
bool Busy;
__fastcall TMyThread();
__fastcall ~TMyThread();
void __fastcall Restart();
};
//------------------------------------------------------------------------------
extern TMyThread *MyThread;
//------------------------------------------------------------------------------
.
TMyThread *MyThread = NULL;
__fastcall TMyThread::TMyThread()
: TThread(true)
{
FreeOnTerminate = true;
Priority = tpNormal;
RestartEvent = new TEvent(nil, true, true, "");
}
__fastcall TMyThread::~TMyThread()
{
delete RestartEvent;
}
void __fastcall TMyThread::UpdateGUI()
{
Form1->Label1 = StatusLine;
}
void __fastcall TMyThread::Execute()
{
while (!Terminated)
{
if (RestartEvent.WaitFor(1000) == wrSignaled)
{
if (Terminated) return;
RestartEvent.ResetEvent();
Busy = true;
StatusLine = "I am doing something!";
Synchronize(&UpdateGUI);
Sleep(2000);
StatusLine = "I am almost done!";
Synchronize(&UpdateGUI);
Busy = false;
}
}
}
void __fastcall TForm1::StartOrRestartThread(TObject *Sender)
{
if (MyThread == NULL)
{
MyThread = new TMyThread();
MyThread->OnTerminate = ThreadTerminated;
MyThread->Start();
}
else if (!MyThread->Busy)
{
MyThread->Restart();
}
else
{
Application->MessageBox(L"Thread is still running please wait!", L"Error", MB_OK);
}
}
void __fastcall TForm1::ThreadTerminated(TObject *Sender)
{
MyThread = NULL;
}