Can you post a project that shows the error?What do you mean?
This is the error declarationYou found the obvious error, but in vain ignored what Thaddy said. In code above the sixth line of code can be executed after the thread is finished and freed. Make all settings in the constructor or call with Suspended = True.
procedure TMainFrm.Go(); var Dt5 : TD3GetDtThr; begin Dt5 := TD3GetDtThr.Create(false); Dt5.OnTerminate:= @ThreadDone; end;
You found the obvious error, but in vain ignored what Thaddy said. In code above the sixth line of code can be executed after the thread is finished and freed. Make all settings in the constructor or call with Suspended = True.
I don't use constructor anymore.All the more need "Suspended = True".
I would still use the constructor, but like so:I don't use constructor anymore.All the more need "Suspended = True".
I would still use the constructor, but like so:I don't use constructor anymore.All the more need "Suspended = True".
I would still use the constructor, but like so:How would you reach a local variable Dt5 in TMainFrm.Go() from TD3GetDtThr.Create() ?????????????
procedure TMainFrm.Go(); var Dt5 : TD3GetDtThr; begin Dt5 := TD3GetDtThr.Create(false); end; constructor TD3GetDtThr.Create(CreateSuspended: boolean); // Set to true or false, see below begin inherited Create(true); // Always call inherited first. MUST be true, so you can also set it directly to true here FreeOnTerminate := True; Dt5.OnTerminate:= @ThreadDone; // Can do that here If CreateSuspended = false then Start; // Now it starts immediately after setup if CreateSuspended = false and manually when true end;
You were right. Dt5 variable won't recognised on thread create procedure.I would still use the constructor, but like so:How would you reach a local variable Dt5 in TMainFrm.Go() from TD3GetDtThr.Create() ?????????????
procedure TMainFrm.Go(); var Dt5 : TD3GetDtThr; begin Dt5 := TD3GetDtThr.Create(false); end; constructor TD3GetDtThr.Create(CreateSuspended: boolean); // Set to true or false, see below begin inherited Create(true); // Always call inherited first. MUST be true, so you can also set it directly to true here FreeOnTerminate := True; Dt5.OnTerminate:= @ThreadDone; // Can do that here If CreateSuspended = false then Start; // Now it starts immediately after setup if CreateSuspended = false and manually when true end;
Anyway, I wouldn't use any hard variable inside TD3GetDtThr because you can't use TD3GetDtThr anywhere else then.
If you really want to, you could override the TD3GetDtThr.Create and pass the ThreadDone as parameter.
I consider that implementation detail, but inherited create(false) will finish so the thread should be running at that point.The thread might be created and running but I don't think the Execute will run before the constructor is finished.
In Delphi we had all kinds of problems because of that. I am not sure about the details for FPC.
My approach is at least a safe approach.
So, back to old code then, without constructor.So, do something like this:
So, back to old code then, without constructor.In that case remember:
But you are correct, that could be en implementation detail which might not be exactly be implemented as I described so your approach will be indeed the safest course.In Delphi documented that the thread starts in the AfterСonstructor. http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.Create (http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.Create), http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.AfterConstruction (http://docwiki.embarcadero.com/Libraries/Rio/en/System.Classes.TThread.AfterConstruction). I looked help in old versions of Delphi, there is the same. Unless in Delphi 1.0 it was not so.
So it is safe to call inherited Create(false) inside the constructor.Good to know.
AfterConstruction is overridden in TThread, it starts the thread if it was created in a suspended state.
By the way, the statement "if CreateSuspended = false then Start;" is not correct (should be removed " = false")??? Of course not. I set create suspended = true during setup and then test if the parameter assumes the thread should be started. But the remark of AfterConstruction I didn't know about.
Then the wiki article needs to be fixed.So it is safe to call inherited Create(false) inside the constructor.Good to know.
But if that's the case, the wiki is not correct.
It says...Please report a bug towards the documentation so that it isn't forgotten.QuoteAfterConstruction is overridden in TThread, it starts the thread if it was created in a suspended state.
Shouldn't it be "if it was created in a non suspended state" then?
In a suspended state the thread is only started after calling start.
A bit OOT, how to call procedure ThreadDone with parameter? Is it possible?Not OT, and yes, it is possible. But not in the 'normal' way.
Please report a bug towards the documentation so that it isn't forgotten.Done
Even though thread Variables Id1 & Id2 declared after thread start, these variable still would be recognized by procedure TD3GetDtThr.Execute. How come?You can't be certain of that.