Recent

Author Topic: Infinite Thread  (Read 4367 times)

zyzmo

  • New Member
  • *
  • Posts: 41
    • My Website
Infinite Thread
« on: November 28, 2018, 08:09:53 pm »
Hello,
I've researched about creating an Infinite Thread, but i didn't found a resolution yet;

My problem is : I have to create a Thread that will execute a verification until a variable receive a value;

I already tried with loops but when I try to destroy the thread object it returns an Access Violation error;
(Just in case, I'm executing thread.terminate and after FreeAndNil(thread));


Thanks!
<!-- Requirement Engineer -->

CCRDude

  • Hero Member
  • *****
  • Posts: 615
Re: Infinite Thread
« Reply #1 on: November 28, 2018, 08:16:27 pm »
Not sure where the exact problem is: the loop or the cleaning up? An thread isn't necessarily terminated right away once you call Terminate. That's why there is a WaitFor as well. Are you checking and reacting to Terminated within that infinite loop?

For loops that might need to wait I prefer TEvent - can be set from the outside, and inside the thread, another TEvent instance can be used with its WaitFor, and the return value evaluated whether it timed out or the signal was send (in that case, exit the loop). If the thread is doing heavy work, another event for the other direction could allow to wait for the thread to be finished.

There are lots of different options on handling threads, I'm sure there are others as good or even better, it depends a lot on the usage scenario :)

lucamar

  • Hero Member
  • *****
  • Posts: 4217
Re: Infinite Thread
« Reply #2 on: November 28, 2018, 08:29:13 pm »
It's rather difficult to debug threads without the code: they can be set and used in so many ways! Show us some code that replicates the issue and we may be able to help more
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

benohb

  • Full Member
  • ***
  • Posts: 218
Re: Infinite Thread
« Reply #3 on: November 29, 2018, 02:09:25 am »

I am satisfied after years that .. destroy or free Thread not an effective way
Since it can not be re-start it or
destroy it
Try creating thousands Thread and free it ..Memory will remain reserved
The best way for me is an Infinite Thread


Code: Pascal  [Select][+][-]
  1. while true do
  2.  begin    
  3.  if Resume then begin
  4.  if Suspend then begin
  5.  end;
« Last Edit: November 29, 2018, 02:13:04 am by benohb »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1590
    • Lebeau Software
Re: Infinite Thread
« Reply #4 on: November 29, 2018, 03:44:56 am »
Code: Pascal  [Select][+][-]
  1. while true do
  2.  

That should be 'while not Terminated' instead, so the thread can be terminated during app shutdown, for instance.  Also, don't forget to check the 'Terminated' property after the thread is "resumed".  During shutdown, be sure to "resume" the thread after 'Terminate()'ing it, if it was "suspended" at the time.

Sounds like you really should be using a thread pool instead, though.  Especially if you can use one that the OS provides for you.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Infinite Thread
« Reply #5 on: November 29, 2018, 03:56:38 pm »
Try creating thousands Thread and free it ..Memory will remain reserved
You do know that would be a very serious bug if it does? Would also be helpful to post an example of such, but now i might just try. I imagine a whole lot of applications rely on threads that are repeatedly created and freed, you should never doubt it works endlessly.

edit: At least after 25000 threads created i don't see any sign of app using up more and more memory. It's going up and down as expected.

This is not threadsafe use of global vars i think, that's why variables don't seem to match up. Make 2 buttons, 3 labels and a TTimer with interval 1:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  9.   StdCtrls;
  10.  
  11. const
  12.   CHUNK_SIZE = 10*1024*1024; // = 10 MB
  13.  
  14. type
  15.  
  16.   { TMyThread }
  17.  
  18.   TMyThread = class(TThread)
  19.   private
  20.     someMemoryChunk: array of byte;
  21.   protected
  22.     procedure Execute; override;
  23.   public
  24.     constructor Create(CreateSuspended: boolean);
  25.     destructor Destroy; override;
  26.   end;
  27.  
  28.   { TForm1 }
  29.  
  30.   TForm1 = class(TForm)
  31.     btnStart: TButton;
  32.     btnStop: TButton;
  33.     Label1: TLabel;
  34.     Label2: TLabel;
  35.     Label3: TLabel;
  36.     Timer1: TTimer;
  37.     procedure btnStartClick(Sender: TObject);
  38.     procedure btnStopClick(Sender: TObject);
  39.     procedure FormCreate(Sender: TObject);
  40.     procedure Timer1Timer(Sender: TObject);
  41.   private
  42.     stopped: boolean;
  43.   public
  44.  
  45.   end;
  46.  
  47. var
  48.   Form1: TForm1;
  49.   ThreadsCreated, ThreadsRunning, ThreadsDestroyed: cardinal;
  50.  
  51. implementation
  52.  
  53. {$R *.lfm}
  54.  
  55. { TMyThread }
  56.  
  57. procedure TMyThread.Execute;
  58. begin
  59.   if not terminated then begin
  60.     inc(ThreadsRunning);
  61.     sleep(50+random(50));
  62.     dec(ThreadsRunning);
  63.     Terminate;
  64.   end;
  65. end;
  66.  
  67. constructor TMyThread.Create(CreateSuspended: boolean);
  68. begin
  69.   inc(ThreadsCreated);
  70.   // Reserve ~10-15 MB
  71.   setlength(someMemoryChunk, CHUNK_SIZE+random(CHUNK_SIZE div 2));
  72.   FreeOnTerminate := true;
  73.   inherited Create(CreateSuspended);
  74. end;
  75.  
  76. destructor TMyThread.Destroy;
  77. begin
  78.   inc(ThreadsDestroyed);
  79.   inherited Destroy;
  80. end;
  81.  
  82. { TForm1 }
  83.  
  84. procedure TForm1.Timer1Timer(Sender: TObject);
  85. var i: integer;
  86. begin
  87.   if not stopped then begin
  88.     i:=ThreadsRunning;
  89.     while i<50 do begin
  90.       inc(i);
  91.       TMyThread.Create(false);
  92.     end;
  93.   end;
  94.   label1.Caption:='Threads created: '+inttostr(ThreadsCreated);
  95.   label2.Caption:='Threads destroyed: '+inttostr(ThreadsDestroyed);
  96.   label3.Caption:='Threads running: '+inttostr(ThreadsRunning);
  97. end;
  98.  
  99. procedure TForm1.FormCreate(Sender: TObject);
  100. begin
  101.   btnStopClick(nil);
  102. end;
  103.  
  104. procedure TForm1.btnStartClick(Sender: TObject);
  105. begin
  106.   stopped:=false;
  107. end;
  108.  
  109. procedure TForm1.btnStopClick(Sender: TObject);
  110. begin
  111.   stopped:=true;
  112. end;
  113.  
  114. end.
« Last Edit: November 29, 2018, 04:38:47 pm by User137 »

mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: Infinite Thread
« Reply #6 on: November 29, 2018, 05:30:52 pm »
not sure if I understood the question fully, but here's something that does what I think you're asking. it uses ezthreads https://github.com/mr-highball/ezthreads

Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. {$ModeSwitch nestedprocvars}
  3. program test_infinite_thread;
  4. uses
  5.   SysUtils,
  6.   ezthreads;
  7.  
  8. procedure InfiniteMethod(Const AThread:IEZThread);
  9. begin
  10.   //execute verification until variable is received
  11.   while not AThread.Exists['variable'] do
  12.     Sleep(300);
  13.  
  14.   //we have the variable now, we're done here
  15.   WriteLn('a variable was: ' + AThread['variable']);
  16. end;
  17.  
  18. var
  19.   LThread:IEZThread;
  20.   LVar:String;
  21. begin
  22.   //setup and start a thread
  23.   LThread:=TEZThreadImpl.Create;
  24.   LThread.Setup(InfiniteMethod).Start;
  25.  
  26.   //read a variable from console
  27.   ReadLn(LVar);
  28.  
  29.   //give variable to thread
  30.   LThread.AddArg('variable',LVar);
  31.  
  32.   //wait until thread has time to respond
  33.   Await;
  34.  
  35.   //wait for user to press something again
  36.   ReadLn;
  37. end.
  38.  

when running with "Hello World" as input, here is the result (output.png)
« Last Edit: November 29, 2018, 05:40:32 pm by mr-highball »

CCRDude

  • Hero Member
  • *****
  • Posts: 615
Re: Infinite Thread
« Reply #7 on: November 29, 2018, 05:48:03 pm »
Sleep is never a good idea, really. Not even in a thread. What if the system shuts down and asks your application to close? It would have to wait 0.3 seconds for the thread.

Let's take Windows for example - if a process takes too long to shut down, it'll recognize the process as non-responsive. If you want to get any kind of certification from Windows, you'll fail right here.

That's why I recommended an event to signal the thread. Waiting for the signal is nearly as low on the CPU as sleep would be, but you can "break" the waiting time at any moment by triggering the event, so your shutdown reaction time is immediate.

mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: Infinite Thread
« Reply #8 on: November 29, 2018, 05:53:53 pm »
@CCRDude sleep can be removed in my example, and simply be written as

Code: Pascal  [Select][+][-]
  1. {$mode delphi}{$H+}
  2. {$ModeSwitch nestedprocvars}
  3. program test_infinite_thread;
  4. uses
  5.   SysUtils,
  6.   ezthreads;
  7.  
  8. procedure InfiniteMethod(Const AThread:IEZThread);
  9. begin
  10.   //execute verification until variable is received, without using sleep
  11.   while not AThread.Exists['variable'] do;
  12.  
  13.   //we have the variable now, we're done here
  14.   WriteLn('a variable was: ' + AThread['variable']);
  15. end;
  16.  
  17. var
  18.   LThread:IEZThread;
  19.   LVar:String;
  20. begin
  21.   //setup and start a thread
  22.   LThread:=TEZThreadImpl.Create;
  23.   LThread.Setup(InfiniteMethod).Start;
  24.  
  25.   //read a variable from console
  26.   ReadLn(LVar);
  27.  
  28.   //give variable to thread
  29.   LThread.AddArg('variable',LVar);
  30.  
  31.   //wait until thread has time to respond
  32.   Await;
  33.  
  34.   //wait for user to press something again
  35.   ReadLn;
  36. end.
  37.  

the output will be the same as before, however the background thread will appear to be working pretty hard. I personally don't mind the sleep method, but if you the delay time is a concern sleep isn't necessary.
« Last Edit: November 29, 2018, 06:00:21 pm by mr-highball »

CCRDude

  • Hero Member
  • *****
  • Posts: 615
Re: Infinite Thread
« Reply #9 on: November 29, 2018, 06:00:18 pm »
Yes, but it's higher on CPU. If the thread is to be working all the time anyway, that's no issue, but if it has times of waiting for input, that's unnecessary.

mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: Infinite Thread
« Reply #10 on: November 29, 2018, 06:00:48 pm »
you beat me to my edit :)

 

TinyPortal © 2005-2018