RAD Studio VCL Reference
ContentsIndex
PreviousUpNext
TThread.Terminated Property

Indicates whether the thread has been asked to terminate.

Pascal
property Terminated: Boolean;
C++
__property Boolean Terminated;

The thread's Execute method and any methods that Execute calls should check Terminated periodically and exit when it's true. The Terminate method sets the Terminated property to true. 

The Terminate method is the polite way to abort the execution of a thread, but it requires cooperation from the thread's Execute code. Using Terminate is recommended over the TerminateThread Win32 API call.  

C++ Examples: 

 

/*
The following example shows how to use the LockList and
UnlockList methods to access a thread-safe version  of a
TList object:
*/

#include <memory> // for the auto_str

class TMyThread : public TThread
{
__published:    // IDE-managed Components
private:    // User declarations
protected:  // User declarations
    void __fastcall Execute();
public:     // User declarations
    __fastcall TMyThread(bool suspended);
};

__fastcall TMyThread::TMyThread(bool suspended)
    : TThread(suspended)
{
}

class TYouThread : public TThread
{
__published:    // IDE-managed Components
private:    // User declarations
protected:  // User declarations
    void __fastcall Execute();
public:     // User declarations
    __fastcall TYouThread(bool suspended);
};

__fastcall TYouThread::TYouThread(bool suspended)
    : TThread(suspended)
{
}

class TListThread : public TThread
{
__published:    // IDE-managed Components
private:    // User declarations
protected:  // User declarations
    void __fastcall Execute();
public:     // User declarations
    __fastcall TListThread(bool suspended);
};

__fastcall TListThread::TListThread(bool suspended)
    : TThread(suspended)
{
}

TThreadList *threadList1;
bool mythreadRunning, youthreadRunning, listthreadRunning;
int globalCount;
TMyThread *secondProcess;
TYouThread *otherSecondProcess;
TListThread *listProcess; // thread arecustom descendants of TThread

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  if (mythreadRunning == FALSE)
  {
    mythreadRunning = TRUE;
    secondProcess = new TMyThread(True); // create suspended – secondprocess does not run yet
    secondProcess->FreeOnTerminate = True; // don't need to cleanup after terminate
    secondProcess->Priority = tpLower;  // set the priority to lower than normal
    secondProcess->Resume(); // now run the thread
  }
  else
    MessageDlg("This thread is still running.  You are going to hurt yourself!",
      mtInformation, TMsgDlgButtons() << mbOK, 0);
}

void __fastcall TMyThread::Execute()
{
  for (int I = 0; I <= 20; I++)
  {
    if (Terminated) break;
    TRadioButton *myRadio = new TRadioButton(Form1); // The owner (Form1) will clean this up.
    globalCount = globalCount + 1;
    myRadio->Name = "RadioButton" + IntToStr(globalCount);
    threadList1->Add(myRadio);
    Sleep(1000);
  }
  mythreadRunning = FALSE;
}

void __fastcall TForm1::Button3Click(TObject *Sender)
{
  if (youthreadRunning == FALSE)
  {
    youthreadRunning = TRUE;
    otherSecondProcess = new TYouThread(True); // create suspended – other secondprocess does not run yet
    otherSecondProcess->FreeOnTerminate = True; // don't need to cleanup after terminate
    otherSecondProcess->Priority = tpLower;  // set the priority to lower than normal
    otherSecondProcess->Resume(); // now run the thread
  }
  else
    MessageDlg("This thread is still running.  You are going to hurt yourself!",
      mtInformation, TMsgDlgButtons() << mbOK, 0);
}

void __fastcall TYouThread::Execute()
{
  for (int I = 0; I <= 10; I++)
  {
    if (Terminated) break;
    try
    {
      TList *list = threadList1->LockList();
      if (2*I < list->Count)
      {
        TControl *Temp = reinterpret_cast<TControl *>(list->Items[2*I]);
        threadList1->Remove(Temp);
      }
    }
    __finally
    {
      threadList1->UnlockList();
    }
    if (Terminated)
      MessageDlg("youThread has been asked to terminate, but is still running!",
        mtInformation, TMsgDlgButtons() << mbOK, 0);
    Sleep(3000);
  }
  youthreadRunning = FALSE;
}

void __fastcall TForm1::Button2Click(TObject *Sender)
{
  if (listthreadRunning == FALSE)
  {
    listthreadRunning = TRUE;
    listProcess = new TListThread(True); // create suspended – secondprocess does not run yet
    listProcess->FreeOnTerminate = True; // don't need to cleanup after terminate
    listProcess->Priority = tpLower;  // set the priority to lower than normal
    listProcess->Resume(); // now run the thread
  }
  else
    MessageDlg("This thread is still running.  You are going to hurt yourself!",
      mtInformation, TMsgDlgButtons() << mbOK, 0);
}

void __fastcall TListThread::Execute()
{
  while(True)
  {
    if (Terminated) break;
    Form1->ListBox1->Clear();
    TList *myList = threadList1->LockList();
    try
    {
      for (int I = 0; I < myList->Count; I++)
      {
        TControl *Temp = reinterpret_cast<TControl *>(myList->Items[I]);
        Form1->ListBox1->Items->Add(Temp->Name);
      }
    }
    __finally
    {
      threadList1->UnlockList();
    }
    Sleep(1000);
  }
}

void __fastcall TForm1::Button4Click(TObject *Sender)
{
  if (secondProcess != NULL)
    secondProcess->Terminate();
  if (otherSecondProcess != NULL)
    otherSecondProcess->Terminate();
}

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  mythreadRunning = FALSE;
  youthreadRunning = FALSE;
  listthreadRunning = FALSE;
  listProcess = NULL;
  secondProcess = NULL;
  otherSecondProcess = NULL;
  static std::auto_ptr<TThreadList> _threadList1Cleaner(threadList1 = new TThreadList());
  for (int I = 1; I <= 5; I++)
  {
    TRadioButton *RadioButton = new TRadioButton(Form1); // The owner (Form1) will clean this up.
    RadioButton->Name = "RadioButton" + IntToStr(I);
    threadList1->Add(RadioButton);
  }
  globalCount = 5;
}

 

Delphi Examples: 

{
The following example shows how to use the LockList and
UnlockList methods to access a thread-safe version  of a
TList object:
}
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button3: TButton;
    ListBox1: TListBox;
    Button2: TButton;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  TListThread = class(TThread)
  protected
    procedure Execute; override;
  end;
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;
  TYouThread = class(TThread)
  protected
    procedure Execute; override;
  end;

var
  Form1: TForm1;
  threadList1: TThreadList;
  mythreadRunning, youthreadRunning, listThreadRunning: Boolean;
  globalCount: Integer;
  listProcess: TListThread; { TListThread is a custom descendant of TThread }
  secondProcess: TMyThread; { TMyThread is a custom descendant of TThread }
  otherSecondProcess: TYouThread; { TMyThread is a custom descendant of TThread }

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  if (mythreadRunning = FALSE) then
  begin
    mythreadRunning:= TRUE;
    secondProcess := TMyThread.Create(True); { create suspended – secondprocess does not run yet }
    secondProcess.FreeOnTerminate := True; { don't need to cleanup after terminate }
    secondProcess.Priority := tpLower;  // set the priority to lower than normal
    secondProcess.Resume; { now run the thread }
  end
  else
    MessageDlg('This thread is still running.  You are going to hurt yourself!',
      mtInformation, [mbOk], 0);
end;

procedure TMyThread.Execute;
var
  I: Integer;
  myRadio: TRadioButton;
begin
  for I := 0 to 20 do
  begin
    if (Terminated) then
    begin
      mythreadRunning:= FALSE;
      exit;
    end;
    myRadio:= TRadioButton.Create(Form1);
    globalCount:= globalCount + 1;
    myRadio.Name:= 'RadioButton' + IntToStr(globalCount);
    threadList1.Add(myRadio);
    Sleep(1000);
  end;
  mythreadRunning:= FALSE;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if (listthreadRunning = FALSE) then
  begin
    listThreadRunning:= TRUE;
    listProcess := TListThread.Create(True); { create suspended – secondprocess does not run yet }
    listProcess.FreeOnTerminate := True; { don't need to cleanup after terminate }
    listProcess.Priority := tpLower;  // set the priority to lower than normal
    listProcess.Resume; { now run the thread }
  end;
end;

procedure TListThread.Execute;
var
  I: Integer;
  Temp: TControl;
  myList: TList;
begin
  while(True) do
  begin
    if (Terminated) then
    begin
      listthreadRunning:= FALSE;
      exit;
    end;
    Form1.ListBox1.Clear;
    myList:= threadList1.LockList;
    try
      for I := 0 to myList.Count-1 do
      begin
        Temp:= myList.Items[I];
        Form1.ListBox1.Items.Add(Temp.Name);
      end;
    finally
      threadList1.UnlockList;
    end;
    Sleep(1000);
  end;
  listthreadRunning:= FALSE;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  if (youthreadRunning = FALSE) then
  begin
    youthreadRunning:= TRUE;
    otherSecondProcess := TYouThread.Create(True); { create suspended – secondprocess does not run yet }
    otherSecondProcess.FreeOnTerminate := True; { don't need to cleanup after terminate }
    otherSecondProcess.Priority := tpLower;  // set the priority to lower than normal
    otherSecondProcess.Resume; { now run the thread }
  end
  else
    MessageDlg('This thread is still running.  You are going to hurt yourself!',
      mtInformation, [mbOk], 0);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  if (listProcess <> nil) then
    listProcess.Terminate;
  if (secondProcess <> nil) then
    secondProcess.Terminate;
  if (otherSecondProcess <> nil) then
    otherSecondProcess.Terminate;
end;

procedure TYouThread.Execute;
var
  I: Integer;
  Temp: TControl;
begin
  for I := 0 to 10 do
  begin
    if (Terminated) then
    begin
      youThreadRunning:= FALSE;
      exit;
    end;
    with threadList1.LockList do
    try
      if (2*I < Count) then
      begin
        Temp:= Items[2*I];
        threadList1.Remove(Temp);
      end;
    finally
      threadList1.UnlockList;
    end;
    if (Terminated) then
      MessageDlg('youThread has been asked to terminate, but is still running!',
        mtInformation, [mbOk], 0);
    Sleep(3000);
  end;
  youthreadRunning:= FALSE;
end;

 

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!