Recent

Author Topic: how to run code in background  (Read 2899 times)

rcmz

  • Full Member
  • ***
  • Posts: 156
how to run code in background
« on: January 03, 2024, 12:43:05 am »
hi,

How can I run code in background?

In Delphi I uses TBackgroundWorker

Any ideas?

TIA
rcmz

cdbc

  • Hero Member
  • *****
  • Posts: 2604
    • http://www.cdbc.dk
Re: how to run code in background
« Reply #1 on: January 03, 2024, 08:07:05 am »
Hi
I think, underneath "TBackgroundWorker" is a thread, sooo use a thread  8)
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

Zvoni

  • Hero Member
  • *****
  • Posts: 3246
Re: how to run code in background
« Reply #2 on: January 03, 2024, 08:08:03 am »
TThread?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 407
  • My software never cras....
Re: how to run code in background
« Reply #3 on: January 03, 2024, 04:02:37 pm »
TThread?

Without objections, I would do:

Code: Pascal  [Select][+][-]
  1. Function Achunkofrealpascal (p:pointer):ptrint;
  2. VAR
  3.    z:somerecord;
  4. BEGIN
  5.    z := somerecord(p^);
  6.    While not z.Shutdown do
  7.       begin
  8.          stuff;
  9.          sleep(z.SleepPeriod);
  10.       end;
  11.    exit(0);
  12. END;
  13.  
  14. //somewhere in main:
  15.   With BlockOfData do
  16.     begin
  17.        Shutdown := false;
  18.        SleepPeriod := 100;  //ms
  19.        Otherstuff := ...
  20.    end;
  21.   TID := BeginThread(@Achunkofrealpascal, @Blockofdata);

Notes: use flags or data in the referenced record to send signals into/out of the background thread.

You can kill the thread using TID as a reference, or (in the case above) by setting Shutdown to true.
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

Jiyahana

  • New Member
  • *
  • Posts: 12
Re: how to run code in background
« Reply #4 on: January 03, 2024, 04:16:39 pm »
You can use TThread specifically by creating a descendant of the TThread class. Implement the code that needs to run in the background within the execute method of the TThread descendant.

Example.

Quote
uses
  System.Classes;

type
  TMyBackgroundThread = class(TThread)
  protected
    procedure Execute; override;
  end;

procedure TMyBackgroundThread.Execute;
begin
  // Perform the background operations here
  // Ensure synchronization if accessing UI elements
end;

Instantiate and start the background thread where needed in your Delphi application.

Quote
var
  MyThread: TMyBackgroundThread;
begin
  MyThread := TMyBackgroundThread.Create(True); // Create suspended
  MyThread.FreeOnTerminate := True; // Auto-free thread when done
  MyThread.Start; // Start the background thread
end;


I hope example will help.

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: how to run code in background
« Reply #5 on: January 03, 2024, 04:56:05 pm »
Not really.
Much easier are the options possible for TThread,ExecuteInThread()
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

rcmz

  • Full Member
  • ***
  • Posts: 156
Re: how to run code in background
« Reply #6 on: January 03, 2024, 06:07:53 pm »
Thx,

I will try it.


KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: how to run code in background
« Reply #7 on: January 03, 2024, 11:42:32 pm »
If its something where you not need to take much care about ...
Code: Pascal  [Select][+][-]
  1. procedure ThreadProc;
  2. begin
  3.   // all code that needs to run threaded belong in here
  4.   Sleep(5000);
  5.   Form1.Button1.Enabled := True;
  6. end;
  7.  
  8. procedure TForm1.Button1Click(Sender: TObject);
  9. var
  10.   AProc: TProcedure;
  11. begin
  12.   Button1.Enabled := False;
  13.   AProc := @ThreadProc;
  14.   TThread.CreateAnonymousThread(AProc).Start;
  15. end;
Have in mind, code will run to its endphase even if you closed your process somehow.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Thaddy

  • Hero Member
  • *****
  • Posts: 18729
  • To Europe: simply sell USA bonds: dollar collapses
Re: how to run code in background
« Reply #8 on: January 04, 2024, 10:33:22 am »
I would still also save the result of the not so anonymous thread, since it returns a valid TThread that can be used later when needed. Comes to mind TThread.CheckTerminated.
If Europe sells their USA bonds the USD will collapse. Europe can affort that given average state debts. The USA can't affort that. Just an advice...

Zvoni

  • Hero Member
  • *****
  • Posts: 3246
Re: how to run code in background
« Reply #9 on: January 04, 2024, 10:57:51 am »
I would still also save the result of the not so anonymous thread, since it returns a valid TThread that can be used later when needed. Comes to mind TThread.CheckTerminated.
Nevermind WaitFor and OnTerminated
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

CM630

  • Hero Member
  • *****
  • Posts: 1607
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: how to run code in background
« Reply #10 on: February 04, 2026, 09:33:53 am »
Code: Pascal  [Select][+][-]
  1. procedure ThreadProc;
  2. begin
  3.   // all code that needs to run threaded belong in here
  4.   Sleep(5000);
  5.   Form1.Button1.Enabled := True;
  6. end;
  7.  
  8. procedure TForm1.Button1Click(Sender: TObject);
  9. var
  10.   AProc: TProcedure;
  11. begin
  12.   Button1.Enabled := False;
  13.   AProc := @ThreadProc;
  14.   TThread.CreateAnonymousThread(AProc).Start;
  15. end;
Have in mind, code will run to its endphase even if you closed your process somehow.

Can this code be modified in order to pass a parameter to ThreadProc? For example, procedure ThreadProc(Sender: TObject);
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

cdbc

  • Hero Member
  • *****
  • Posts: 2604
    • http://www.cdbc.dk
Re: how to run code in background
« Reply #11 on: February 04, 2026, 10:04:49 am »
Hi
Yes, in multiple ways  ;D
But I think, the easiest way is to use one of its siblings, namely:
Code: Pascal  [Select][+][-]
  1.     Class Function ExecuteInThread(AMethod : TThreadExecuteCallback; AData : Pointer = Nil; AOnTerminate: TNotifyCallBack = Nil) : TThread; overload;static;
This class method is /lifted/ from TThread in FPC 3.2.2...
With that you get:
· a proc to execute in the thread
· a 'pointer' param to said procedure - remember 'TObject' is just a pointer...
·· the pointer param, you just typecast to the proper type, first thing in proc.
· a callback-proc to execute, when the thread terminates...

What more could you ask for?!?  8)
Oh and btw. the 'AData' & 'AOnTerminate' can be nil, without hassle.
Try and give that a whirl... :D
Regards Benny

Ps.: It's all there in the source, have a good 'looksee' in there...
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

CM630

  • Hero Member
  • *****
  • Posts: 1607
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: how to run code in background
« Reply #12 on: February 05, 2026, 09:17:23 am »
I did not find examples for ExecuteInThread (except some in delphimode), maybe I should try harder.

What I did is:

Code: Pascal  [Select][+][-]
  1.   TUpdatePortsThread = class(TThread)
  2.     private
  3.  
  4.     protected
  5.       procedure Execute; override;
  6.     public
  7.       Owner: TCustomComboBox;
  8.       Constructor Create(CreateSuspended : boolean);
  9.   end;
  10.  
  11.  
  12. ...
  13. constructor TUpdatePortsThread.Create(CreateSuspended : boolean);
  14. begin
  15.   inherited Create(CreateSuspended);
  16.   FreeOnTerminate := True;
  17. end;
  18.  
  19. procedure TUpdatePortsThread.Execute;
  20. begin
  21.   try
  22.     Application.QueueAsyncCall(@TSerialSelector(Owner).UpdatePorts,0);
  23.   finally
  24.     Terminate;
  25.   end; //try
  26. end;

The program crashes, I have a suspicion why it does, but anyway, when it does not crash it hangs until called function is complete  :o
I am wondering if is QueueAsyncCall that hangs my interface, despite using a thread.
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

cdbc

  • Hero Member
  • *****
  • Posts: 2604
    • http://www.cdbc.dk
Re: how to run code in background
« Reply #13 on: February 05, 2026, 09:43:33 am »
Hi
I have to run an errin, so if you can wait a little bit, I'll write you an example of use of the above 'ExecuteInThread', when I get back...
Otherwise I'll need more info, to be able to help you... Ok?

Ps.: Your use of 'QueueAsyncCall' in this situ, defeats the use of a thread, the code you want run, runs in the main thread!!! Not exactly your aim  :-[

Regards Benny
« Last Edit: February 05, 2026, 09:47:20 am by cdbc »
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

CM630

  • Hero Member
  • *****
  • Posts: 1607
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: how to run code in background
« Reply #14 on: February 05, 2026, 10:16:31 am »
...
I have to run an errin, so if you can wait a little bit, I'll write you an example of use of the above 'ExecuteInThread', when I get back...
...
Thanks, waiting a few days (weeks) is not an issue. But if Threads are not a cure, there is no point to write an example (though writing to wiki is usually a good thing).

If I do not run the routine with QueueAsyncCall the app crashes (https://forum.lazarus.freepascal.org/index.php/topic,24490.msg572378.html#msg572378) - sometimes executing one of the lines of the routine takes more than five seconds, when it happens faster, everything is fine.

So if threads do not help, what else could I do? Run the routine in a virtual form and somehow signal the main form when the data is ready?
Or maybe it I should seek a less impatient WMI query routine.

Edit: I made some changes to the WMI caller; it seems to work without asynccall now. I will retry with threads these days.
« Last Edit: February 05, 2026, 01:08:26 pm by CM630 »
Лазар 4,4 32 bit (sometimes 64 bit); FPC3,2,2

 

TinyPortal © 2005-2018