Recent

Author Topic: TThread terminated value in constructor and Execute.  (Read 4440 times)

valerife

  • New Member
  • *
  • Posts: 10
TThread terminated value in constructor and Execute.
« on: November 30, 2016, 11:59:54 am »
Hello,

I am writing a simple program and i am facing an issue with the TThread class.
I would like to handle the error in my create and set Terminate to true in my constructor if something wrong happen in my initialisation.
However the really weird thing is this :
The value of Terminated in my constructor is False, (i printed it before and after the inherited Create(False) of the TThread class) and true in my execute

Here is an example of my issue :

Code: Pascal  [Select]
  1.  
  2. {$mode objfpc}{$H+}
  3.  
  4. uses
  5.     {$ifdef unix}
  6.     cthreads,
  7.     cmem,
  8.   {$endif} heaptrc, Classes, SysUtils, MyThread;
  9. var
  10.   MyThread : TMyThread;
  11. begin
  12.   try
  13.    try
  14.      MyThread := MyThread.Create;
  15.    Except
  16.      on E : Exception do
  17.         writeln(E.Message);
  18.    end;
  19.   finally
  20.     FreeAndNIl(MyThread);
  21.   end;
  22. end.
  23.  

Code: Pascal  [Select]
  1. TMyThread = class(TThread)
  2. public
  3.       constructor Create;
  4.       destructor Destroy; override;
  5.       procedure Execute; override;                        
  6. end;
  7.  
  8. constructor TMyThread.Create;
  9. begin
  10.   if (Terminated) then writeln('The value is TRUE before Inherited in Constructor'); else writeln('The value is FALSE before Inherited in Constructor');
  11.   inherited Create(False);
  12.   if (Terminated) then writeln('The value is TRUE after Inherited in Constructor'); else writeln('The value is FALSE after Inherited in Constructor');
  13. end;
  14.  
  15. destructor TMyThread.Destroy;
  16. begin
  17.   inhertied Destroy;
  18. end;
  19.  
  20. procedure TMythread.Excecute;
  21. begin
  22.   if (Terminated) then writeln('The value is TRUE in Execute '); else writeln('The value is FALSE in execute');
  23. end;
  24.  

In console output i will have :

Quote
The value is FALSE before Inherited in Constructor
The value is FALSE after Inherited in Constructor
The value is TRUE in Execute


Is this Normal ?

Thank you very much !

Cyrax

  • Hero Member
  • *****
  • Posts: 758
Re: TThread terminated value in constructor and Execute.
« Reply #1 on: November 30, 2016, 01:48:52 pm »
It is. Inside your TThread constructor, there is no time for OS to switch execution from main thread to your thread.

You need to add call to ThreadSwitch (preferably inside While not Terminated loop)  procedure after inherited Create(..) clause to achieve the result you seek.

valerife

  • New Member
  • *
  • Posts: 10
Re: TThread terminated value in constructor and Execute.
« Reply #2 on: November 30, 2016, 01:54:03 pm »
Hi Cyrax,

Thanks you for your answer.
My issue right here is the value of Terminated is True in the Execute, i can t do a While not terminated loop in the Execute.
I might have missunderstand somethine in the TThread class about value of terminated ?


User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TThread terminated value in constructor and Execute.
« Reply #3 on: November 30, 2016, 02:35:31 pm »
Use some different boolean variable to tell that there was error maybe? Assign it in Create and check at beginning of Execute. That way you have control that it won't enter the loop at all.

valerife

  • New Member
  • *
  • Posts: 10
Re: TThread terminated value in constructor and Execute.
« Reply #4 on: November 30, 2016, 02:47:50 pm »
I think i will go for something like this. I thought it was cleaner to use the terminated boolean of the TThread class however it look causing more issues (if i am using it correctly).

Thank you

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 675
    • Lebeau Software
Re: TThread terminated value in constructor and Execute.
« Reply #5 on: November 30, 2016, 10:49:21 pm »
Your example code is destroying the TThread object as soon as its constructor exits.  That code happens to be running before Execute() has started running.  I don't know if FreePascal's TThread destructor works the same way as Delphi's TThread destructor, but in Delphi, if TThread is still running when it is being destroyed, the destructor calls Terminate() and waits for the thread to finish running before then releasing its resources from memory.  That would certainly explain why you see Terminated is True in Execute().
« Last Edit: November 30, 2016, 10:53:08 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TThread terminated value in constructor and Execute.
« Reply #6 on: December 01, 2016, 04:21:59 am »
Looking more closely i don't actually understand what's going on. Is it a Lazarus or fpc bug? He isn't calling destroy or terminate at any point, so i don't think it should behave like that. Suspended parameter true or false shouldn't affect that, it only determines if thread starts with or without Start command.

But also i couldn't compile your code. There are even typos like "TMythread.Excecute;" and semicolons in wrong places of IF statements. I tried it with modifications with simple console app and so on, and all i get is sigsegv after at most 1 line printed to console. If you run a thread on console app, shouldn't you have some sort of main loop? I didn't try this as TForm based app which would actually be simpler. But then you can't use writeln().

edit: Oops, yes he is destroying with
Code: Pascal  [Select]
  1. finally
  2.     FreeAndNIl(MyThread);

tetrastes

  • New Member
  • *
  • Posts: 36
Re: TThread terminated value in constructor and Execute.
« Reply #7 on: December 01, 2016, 09:19:40 am »
I didn't try this as TForm based app which would actually be simpler. But then you can't use writeln().

Windows is not the only OS  ;D

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: TThread terminated value in constructor and Execute.
« Reply #8 on: December 01, 2016, 02:48:21 pm »
I didn't try this as TForm based app which would actually be simpler. But then you can't use writeln().

Windows is not the only OS  ;D
And even it it was:

Uncheck Project->Options->Config & Target->Target-Specific Options->Win32 gui application

Besides that, last time i checked writeln was not thread safe.

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: TThread terminated value in constructor and Execute.
« Reply #9 on: December 03, 2016, 03:47:39 am »
Linux and mac gui apps need that switch too?

molly

  • Hero Member
  • *****
  • Posts: 2345
Re: TThread terminated value in constructor and Execute.
« Reply #10 on: December 03, 2016, 04:33:41 am »
Linux and mac gui apps need that switch too?
afaik, no. That is a Windows only switch. See also here.

For windows applications this is required so that the lazarus application automatically assigns input and output handles to a console. If you don't uncheck that configuration option, then there will be no input and output handles assigned and that will cause an I/O error when invoking a call to read/write.

afaik input and output handles are always available under Linux and MacOS.

So, for Linux and Mac this should work out of the box. In case you don't have any visible output then you can use the run parameter options. In case you have that configured to automatically close your terminal on program exit, then you should add a readln just before your app terminates (which works in a similar way when using Windows). Most small test applications exits too quickly, in which case you are unable to see/read the terminal output.