-1

I created a new class derived from TThread class, and on the constructor i call "inherited Create(True);", and then call "Resume()" since i have override the Execute() call, now i wanna recall the Execute() (Run the Thread Again) without destroying the class instance, so i have a function inside the new class called "myRestart()", which recalls "inherited Create(True);" and makes me able to call "Resume()" again and thread works again.

my question is, is this a safe practice? will it work also if i have multiple instances of this class? or is there a better way to do it?

thanks

  • 5
    Rather than describing the code, show it. – David Heffernan Nov 26 '12 at 09:32
  • One also wonders why you would create a thread suspended and then resume it in the constructor. Don't create it suspended in the first place. – David Heffernan Nov 26 '12 at 14:15
  • that's not a safe practice. it will not work as you want even with a single instance and yes, there are better ways to do it. But... what you want exactly to do at the end? – jachguate Nov 26 '12 at 15:42
  • @DavidHeffernan - in earlier versions of Delphi, there was a good chance that the thread, if instantiated with 'inherited Create(False)' would run immediately upon that call and before the ctor had finished creating/initializing fields. This gave rise to threads trying to wait on queues that did not exist yet and similar disasters. AFAIK, later Delphi versions always create the OS thread suspended upon the inherited call and just store the parameter so that the OS thread can be run/remain suspended when the ctor returns. – Martin James Nov 26 '12 at 16:35
  • @Martin In Delphi 7 (and earlier) the thread doesn't get resumed until AfterConstruction – David Heffernan Nov 26 '12 at 16:52
  • @DavidHeffernan, see Rob's answer here: [Wich is the correct way to start a suspended thread in delphi 2007?](http://stackoverflow.com/a/4206993/576719). He claims that the risk of starting the thread prior to finishing the constructor was fixed in D6. – LU RD Nov 26 '12 at 18:12
  • @LURD - sounds about right - I know it could happen in D3/D5. – Martin James Nov 26 '12 at 19:42
  • @MartinJames, searched in the QC archives, [`QC6137`](http://qc.embarcadero.com/wc/qcmain.aspx?d=6137). – LU RD Nov 26 '12 at 20:25
  • i'm not starting the thread as soon as it's created, it waits for user action after settings some properties. i recreate it in order to run the same instance with same properties over and over again, not on create cause that would defy the whole thing, since i don't need to recreate, why would i create suspended then resume in constructor if i call constructor only once? – Zakri Vorschted Nov 26 '12 at 21:46
  • @ZakriVorschted, then Martin has provided a solid solution for you. Create the thread with the event unsignalled. Every time you want the thread.Execute to run, set the event. When your work is done, reset the event. If we misunderstood something, then please clearify with a code example. – LU RD Nov 27 '12 at 08:47

2 Answers2

4

Don't go around doing things like that. If you want procedures/functions in your thread class to run more than once, call them from a while() loop in your Execute override and signal the thread to run the code with a suitable synchro object at the top, a semaphore or event, say:

TmyThread.Execute;
begin
  while true do
  begin
    someEvent.waitFor(INFINITE);
    if terminated then exit;
    doMyProcedure(params);
    doOtherStuff;
  end;
end;
Martin James
  • 24,453
  • 3
  • 36
  • 60
-1

I think you must show your Restart Code? Because as I know if the thread finish it's Execute procedure then It's state in OS will change to DONE and calling resume again only start that thread as just a function in main thread not a real separate thread.

by the way you can use this sample code for your need

unit UWorker;

interface

uses Windows, Classes, Contnrs;

type
  TWorkerThread=class;

  TWorkerJob=class
    procedure ExecuteJob(Worker: TWorkerThread); virtual; abstract;
  end;

  TWorkerThread=class(TThread)
  private
    FFinished: TObjectList;
    FNotFinished: TObjectList;
  protected
    procedure Execute;Override;
  public
    constructor Create(createSuspended: Boolean);override;
    destructor Destroy; override;
  public
    property Finished: TObjectList read FFinished;
    property NotFinished: TObjectList read FNotFinished;
  end;



implementation

{ TWorkerThread }

constructor TWorkerThread.Create(createSuspended: Boolean);
begin
  inherited;
  FFinished := TObjectList.Create;
  FNotFinished := TObjectList.Create;
end;

destructor TWorkerThread.Destroy;
begin
  FFinished.Free;
  FNotFinished.Free;
  inherited;
end;

procedure TWorkerThread.Execute;
var
  CurrentJob: TWorkerJob;
begin
  while not Terminated do
  begin
    if FNotFinished.Count > 0 then
    begin
      CurrentJob := TWorkerJob(FNotFinished.Items[0]);
      FNotFinished.Extract(CurrentJob);

      with CurrentJob do
      begin
        ExecuteJob(Self);
      end;
      FFinished.Add(CurrentJob);
    end else
    begin
      // pass the cpu to next thread or process
      Sleep(5);
    end;
  end;

end;

end.

for use this code just create a worker and then create some instance of jobs and add them to NotFinished list. the Worker will execute all jobs one by one. To restart a job just extract it from Finished list and add it again to the NotFinished.

remember you must inherit your jobs and override the ExecuteJob procedure.

Mahdi
  • 247
  • 2
  • 6
  • -1 TObjectList is not thread safe! Adding and removing objects from different threads the way you pretend to do here will drive the application that uses your code to failure, sooner or later. You have to coordinate the list add/substract or use a thread safe list! – jachguate Nov 26 '12 at 15:40
  • Dear every programmer know that should protect shared objects with synchronize objects like mutex or use the synchronize method of thread so I omit that part of code. – Mahdi Dec 02 '12 at 13:08
  • Re-read the OP question. Do you really think the OP knows how to protect that? Believe me, lots of programmer dont hace a clue about threads, memory protection or synch. On the other hand, tere's thread safe queues and lists out there. IMHO no code example is better than a poorly coded one. – jachguate Dec 02 '12 at 18:15