Forum > General

TThread - Why can't I start a thread again?

(1/2) > >>

Slawek:
Hello,

I made such an example:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls; type  TShowStatusEvent = procedure(Status, Task: String) of Object;   { TMyThread }   TMyThread = class(TThread)  private    fStatusText : string;    fTaskText : string;    FOnShowStatus: TShowStatusEvent;    procedure ShowStatus;  protected    procedure Execute; override;  public    constructor Create(CreateSuspended : boolean);    property OnShowStatus: TShowStatusEvent read FOnShowStatus write FOnShowStatus;  end;   { TForm1 }   TForm1 = class(TForm)    btStart: TButton;    btStop: TButton;    laTask: TLabel;    laStatus: TLabel;    procedure btStartClick(Sender: TObject);    procedure btStopClick(Sender: TObject);    procedure FormCreate(Sender: TObject);    procedure FormDestroy(Sender: TObject);  private    MyThread: TMyThread;    procedure ShowStatus(Status, Task: string);  public   end; var  Form1: TForm1; implementation {$R *.lfm} { TMyThread } procedure TMyThread.ShowStatus;begin  if Assigned(FOnShowStatus) then begin    FOnShowStatus(fStatusText, fTaskText);  end;end; procedure TMyThread.Execute;var i: Integer;begin  fStatusText := 'TMyThread Starting...';  Synchronize(@ShowStatus);  fStatusText := 'TMyThread Running...';  while (not Terminated) do begin //repeat all tasks    for i:= 1 to 9 do begin      if Terminated then Break; //abort      fTaskText:='Task no '+i.ToString;      sleep(500);      if not Terminated then        Synchronize(@Showstatus);    end;  end;end; constructor TMyThread.Create(CreateSuspended: boolean);begin  inherited Create(CreateSuspended);end; { TForm1 } procedure TForm1.btStartClick(Sender: TObject);begin  btStart.Enabled:=False;  laStatus.Caption:='Started';  MyThread.Start;  btStop.Enabled:=True;end; procedure TForm1.btStopClick(Sender: TObject);begin  btStop.Enabled:=False;  MyThread.Terminate;  MyThread.WaitFor;  laStatus.Caption:='Terminated';  btStart.Enabled:=True;end; procedure TForm1.FormCreate(Sender: TObject);begin  btStop.Enabled:=False;  MyThread := TMyThread.Create(true);  MyThread.FreeOnTerminate := False;  MyThread.OnShowStatus := @ShowStatus;end; procedure TForm1.FormDestroy(Sender: TObject);begin  if Assigned(MyThread) then begin    MyThread.Terminate;    MyThread.WaitFor;  end;end; procedure TForm1.ShowStatus(Status, Task: string);begin  laStatus.Caption := Status;  laTask.Caption := Task;end; end. 
I can start and stop it, but when I want to start it again, the tasks in the thread are not executed. Even "TMyThread Starting..." is not displayed.
Should the thread stop be done differently in this example? Of course, I'm not talking about a pause. I want to stop the thread completely and then start it again. Unfortunately, I don't know why it doesn't start again.

If I move the thread creation (marked fragment) to btStartClick then everything works. Can a created thread be run only once?


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.btStartClick(Sender: TObject);begin  btStart.Enabled:=False;  MyThread := TMyThread.Create(true);  MyThread.FreeOnTerminate := True;  MyThread.OnShowStatus := @ShowStatus;  laStatus.Caption:='Started';  MyThread.Start;  btStop.Enabled:=True;end;

cdbc:
Hi

--- Quote ---Can a created thread be run only once?
--- End quote ---
Yes. When you exit the Execute method, the thread is done. I.e. you must create it anew. Try to follow TThread in the source, how it gets created etc...
Then you'll see that, Execute IS the ThreadFunc. TThread just adds a lot of clever stuff to the mix  ;)
Hth - Regards Benny

Slawek:

--- Quote from: cdbc on February 08, 2023, 01:36:08 pm ---Hi

--- Quote ---Can a created thread be run only once?
--- End quote ---
Yes. When you exit the Execute method, the thread is done. I.e. you must create it anew.

--- End quote ---
That explains a lot to me. Thank you for your response.


--- Quote from: cdbc on February 08, 2023, 01:36:08 pm ---Try to follow TThread in the source, how it gets created etc...
Then you'll see that, Execute IS the ThreadFunc.

--- End quote ---
I can't find it, but I believe you it is.

cdbc:
Hi Slawek
In the source editor, [ctrl + left-click] on TThread, editor will jump to its implementation, then [ctrl + shift + down arrow] will jump from interface to implementation... Try to follow TThread.Create(...), then you'll see "SysCreate(CreateSuspended, StackSize);" at the end, ctrl-click on that and then ctrl-shift-down... There's some pretty clever stuff in there  ;)
If you must, you can google for "sleeping threads", OmniThreadLibrary https://github.com/gabr42/OmniThreadLibrary implements them and I think EZThreads does too... https://github.com/mr-highball/ezthreads
... or you can roll your own  :D
Have fun - Regards Benny

Slawek:
Thank you very much for this information and links. I'm just getting started with threads. This is not an easy topic. I need to calmly analyze, test and sort everything out in my head  :)
There is quite a lot of knowledge about threads on the internet and on this forum, but so far it seems chaotic to me.

Navigation

[0] Message Index

[#] Next page

Go to full version