Recent

Author Topic: [SOLVED] Variable Procedure in Thread Class ?  (Read 14909 times)

mas steindorff

  • Hero Member
  • *****
  • Posts: 560
Re: Variable Procedure in Thread Class ?
« Reply #15 on: December 05, 2012, 07:28:10 pm »
this has always worked for me
Code: [Select]
   TShowStatusEvent = procedure(status:string) of object;
...
  { TThreadComm }
  TThreadComm = class(TThread)
  private     { private declarations }
...
    FOnShowStatus  :TShowStatusEvent;
  public 
    property OnShowStatus :TShowStatusEvent read FOnShowStatus Write FOnShowStatus;
  end;

implementation 
procedure TThreadComm.ShowStatus2;
begin
  if assigned(FOnShowStatus) then
    begin
      FOnShowStatus(fStatusText);
    end;
end;
...
  fStatusText := 'Thread Says Hello';   // this one is printed
  Synchronize(@ShowStatus2); 
...

Then in the main code

Code: [Select]
procedure Tfrm.MyShowStatus(str:string);
begin
   memo1.lines.add(str)
end;

procedure Tfrm.FormCreate(Sender: TObject);
...
  MyComObj := TThreadComm.Create(TRUE);
  MyComObj.OnShowStatus := @MyShowStatus;
  ...
end;
this lets the thread print msgs directly on the forms' status bar. 
« Last Edit: December 05, 2012, 07:30:57 pm by mas steindorff »
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

Fred vS

  • Hero Member
  • *****
  • Posts: 3780
    • StrumPract is the musicians best friend
Re: Variable Procedure in Thread Class ?
« Reply #16 on: December 05, 2012, 07:40:43 pm »
@ mas steindorff : many thanks but ShowStatus2 is declared inside the Thread :

Code: [Select]
procedure TThreadComm.ShowStatus2;
begin
  if assigned(FOnShowStatus) then
    begin
      FOnShowStatus(fStatusText);
    end;
end;

Whats if procedure ShowStatus2 is a procedure in main form ?

I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Variable Procedure in Thread Class ?
« Reply #17 on: December 05, 2012, 07:55:22 pm »
OK. It seems to threading problem rather than procedure variable issue.
Did you try multithreadingexmple1 ? I tried it now, works. I also tried to add there one procedure and run it via procedure variable. All worked.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

mas steindorff

  • Hero Member
  • *****
  • Posts: 560
Re: Variable Procedure in Thread Class ?
« Reply #18 on: December 05, 2012, 08:37:24 pm »
@ mas steindorff : many thanks but ShowStatus2 is declared inside the Thread :

Code: [Select]
procedure TThreadComm.ShowStatus2;
begin
  if assigned(FOnShowStatus) then
    begin
      FOnShowStatus(fStatusText);
    end;
end;

Whats if procedure ShowStatus2 is a procedure in main form ?

FOnshowStatus is a variable (pointer) that is loaded with the address of the main form's procedure "myShowStatus" after the thread is created by the main form.  the line "FOnShowStatus(fStatusText);" is really "myShowStatus(fStatusText)" so it is in affect a main form procedure.
 
The thread is a tool the main form uses so it should have the choice on how it's used.  in this case, a call is made to myShowStatus() but it once was possible to directly assign a value to a caption or text field.  That has slowly gone away as things like tb.caption have changed from simple variables like strings into properties.  you are really calling the set code of the object and not just setting memory values.  As a thread, that is a bad thing to do.

With that said, the "Synchronize(@ShowStatus2); " command is placing a request in the main form's thread to come and run "ShowStatus2" (more or less) so with in that code, you should be able to access elements of the main form, at least for a few more years  :)

windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

Fred vS

  • Hero Member
  • *****
  • Posts: 3780
    • StrumPract is the musicians best friend
Re: Variable Procedure in Thread Class ?
« Reply #19 on: December 05, 2012, 08:39:18 pm »
Quote
Did you try multithreadingexmple
Of course, it is my favorite  ::)

But i block for how to launch a external procedure encapsulated into a variable.

How do you do it ?
« Last Edit: December 05, 2012, 08:43:03 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: Variable Procedure in Thread Class ?
« Reply #20 on: December 05, 2012, 08:59:14 pm »
Code: [Select]
unit MainUnit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs;

type

  { TMyThread }

  TMyThread = class(TThread)
  private
    fStatusText: string;
    procedure ShowStatus;
  protected
    QQQ: procedure of Object;
    procedure Execute; override;
  public
    constructor Create(CreateSuspended: boolean);
  end;

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
  public
    procedure XXX;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  MyThread : TMyThread;
begin
  MyThread := TMyThread.Create(True); // With the True parameter it doesn't start automatically
  if Assigned(MyThread.FatalException) then
    raise MyThread.FatalException;
     
  // Here the code initialises anything required before the threads starts executing
  MyThread.QQQ:=@XXX;
  MyThread.Start;
end;

{ TMyThread }

procedure TMyThread.ShowStatus;
// this method is only called by Synchronize(@ShowStatus) and therefore
// executed by the main thread
// The main thread can access GUI elements, for example Form1.Caption.
begin
  Form1.Caption := fStatusText;
end;

procedure TForm1.XXX;
begin
  Writeln('sfdghjf');
end;

procedure TMyThread.Execute;
var
  newStatus : string;
begin
  fStatusText := 'TMyThread Starting ...';
  Synchronize(@Showstatus);
  fStatusText := 'TMyThread Running ...';
  while (not Terminated) and (true {any condition required}) do begin
    sleep(50);
    //here goes the code of the main thread loop
    newStatus:='TMyThread Time: '+FormatDateTime('YYYY-MM-DD HH:NN:SS',Now);
             
    if NewStatus <> fStatusText then begin
      QQQ;
      fStatusText := newStatus;
      Synchronize(@Showstatus);
    end;
  end;
end;

constructor TMyThread.Create(CreateSuspended: boolean);
begin
  FreeOnTerminate := True;
  inherited Create(CreateSuspended);
end;

end.                             
Here it is.
QQQ is procedure variable.
XXX is assigned method (e.g. procedure of object).
XXX is assigned  to QQQ in Form.Create
QQQ; is called from TMyThread.Execute
I also added sleep(50); to reduce CPU load.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

Fred vS

  • Hero Member
  • *****
  • Posts: 3780
    • StrumPract is the musicians best friend
Re: Variable Procedure in Thread Class ?
« Reply #21 on: December 05, 2012, 11:21:59 pm »
Yeeep i get it and ..... it seems it was not my fault.  :-[

Many thanks to everybody but the problem is elsewhere.

Your codes and mine are working perfectly if we do not use a parent Procedure of Object.

If Endproc is declared inside TThread, no probem, it works.

But if Endproc is declared in parent of TThread it do not work :

Quote
TThread.execute;
begin
  Synchronize(Parent.EndProc) ; <<<< Not working because Parent
end;

Quote
TThread.execute;
begin
  Synchronize(EndProc) ; <<<< Working because Endoc declared in Thread.
end;

I gonna create a new topic do explain it better.

So for resume, here how to run a external procedure stored in variable into a procedure who is inside a thread :

Code: [Select]
type
    TMyClass = class(TThread)
 Public
 ...
    EndProc  :  procedure of object; //<<< the Outside procedure is declared inside the Cass.
...
  procedure Execute; override;          //<<< the Inside procedure
      end;
///////////////////////////////////////////////////////// 
Procedure    TMyClass.Execute;   //<<< the Inside procedure
begin
....
EndProc ;  //<<< the Outside procedure
end;     

and how to use it in a Form:

Code: [Select]
rocedure procclasstest ; //< the general procedure to test
var
testclass : TMyClass;
begin
testclass :=TMyClass.Create;
testclass.EndProc := @testendproc;  //< the external procedure
testclass.MyClassProc ;
end;

Procedure testendproc;  //< the external procedure
begin
form1.caption := 'It is the End' ;
end;

Ouf, it was a Big fight, but we win.  :-X

« Last Edit: December 06, 2012, 01:34:22 am by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

vfclists

  • Hero Member
  • *****
  • Posts: 1157
    • HowTos Considered Harmful?
Re: [SOLVED] Variable Procedure in Thread Class ?
« Reply #22 on: December 06, 2012, 04:30:19 am »
If your error comes from not understanding something which is properly explained in the FPC/Lazarus documentation, then I suggest you look it up and explain where and how your approach was wrong.

That is a lot better than what amounts to an anecdote, even if it is correct.
Lazarus 3.0/FPC 3.2.2

 

TinyPortal © 2005-2018