Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How do I write a simple TThread object?

Performance

How do I write a simple TThread object?

by  djjd47130  Posted    (Edited  )
Threads mean a lot with the latest computer technology. They allow you to perform multiple tasks at the same time without them interfering with each other. For example, imagine a road. If this road is only 1 lane, and there is a large truck driving slowly, then everyone else gets stuck behind that truck and cannot pass. When the road has two lanes, all the faster moving cars can move over to the other lane and pass the slow truck.

Threads allow similar capabilities: One block of code can be running on its own while another block of code is also running on its own - in the same application. By default, any simple application has its own main thread. You have the choice of adding more threads to allow more things to go on at the same time. For example, you might need to write a thread which performs some very lengthy calculations, while allowing the main GUI thread to continue responding.

This example is using the TThread object which comes with Delphi. There are other ways of performing multi-threaded tasks, including directly using a Critical Section or by using some other multithreading library, such as OmniThreadLibrary.

Code:
type
  TMyThread = class(TThread)
  private
    FActive: Bool;
    FSomeList: TStringList;
    procedure SYNC_Something;
    procedure SYNC_Started;
    procedure SYNC_Stopped;
    procedure SetActive(const Value: Bool);
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
    property Active: Bool read FActive write SetActive;
  end;

This is a basic structure of a thread object. The property Active allows you to turn your thread on/off. Execute is the main procedure where all the threaded work is done. This must be overridden. SYNC_Something is a procedure which is called from inside the thread which tells the thread to do something outside the thread. This is simply because you should not directly call code in one thread from another thread.

Now, for the implementation...

Code:
constructor TMyThread.Create;
begin
  inherited Create(True); //You practically always need to pass 'True' because 'False' is just meaningless...
  FSomeList:= TStringList.Create;
  Resume; //Now that everything is created, we officially start the thread.
end;

destructor TMyThread.Destroy;
begin
  FActive:= False; //Make sure our process is stopped...
  WaitFor; //Wait for the process to stop before we continue freeing things...
  FSomeList.Free;
  inherited;
end;

procedure TMyThread.SetActive(const Value: Bool);
begin
  //Not necessary to be a procedure setter, but you might want to do some preparation at this point...
  FActive:= Value;
end;

procedure TMyThread.Execute;
var
  X: Integer;
begin
  //Everything done inside here, and any procedures called from inside here, are done from within this thread...
  while not Terminated do begin //Keep looping at all times until thread is terminated...
    if FActive then begin //Should this thread be doing something?
      Synchronize(SYNC_Started);

      //START threaded code
      FSomeList.Clear;
      for X := 1 to 1000 do begin
        FSomeList.Append('Some Random Text');
        Synchronize(SYNC_Something);
      end;
      //END threaded code

      Synchronize(SYNC_Stopped);
    end else begin
      Sleep(1); //This keeps the thread from going crazy and maxing the processor...
    end;
  end;
end;

procedure TMyThread.SYNC_Something;
begin
  //Now we can do something which accesses the outside of the thread
  //This would presumably trigger an event notifying the main thread that something has been done or needs to be done
end;

procedure TMyThread.SYNC_Started;
begin
  //Now we can do something which accesses the outside of the thread
  //This would presumably trigger an event notifying the main thread that this thread has begun its work
end;

procedure TMyThread.SYNC_Stopped;
begin
  //Now we can do something which accesses the outside of the thread
  //This would presumably trigger an event notifying the main thread that this thread has finished its work
end;

Whenever you wish to do something inside the thread which involves contacting the outside of the thread in any way, such as triggering an event, you need to synchronize these changes. You cannot simply call something like Form1.Caption := SomeStringInsideTheThread; because there might be something else trying to access this property at the same time, from another thread. Instead, using Synchronize() will allow you to safely contact the outside of the thread.

Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top