[DUG] Terminating a thread
Nick Fauchelle
nick at unica.co.nz
Fri Sep 22 09:37:57 NZST 2006
Stefan,
I have the TTimer there so I can have a timer displayed on my form so
the user can see how long the process has taken. Perhaps I should move
the Timer out of the Thread and have it on the form instead.... and
then I guess with my OnTerminate I could synchronize a call to
ProgTimer.Enabled := false.
Would that be a better option?
I couldn't do the sleep option below as im not trying to Sleep the
program, more just keep a label updated with a count of the time.
Thanks :-)
Stefan Mueller wrote:
> Timers in a thread sounds indeed very dodgy! - TTimer works with windows
> messages (messageloop from your mainthread ... and you are calling into your
> own thread - this is a big no-no!).
>
> Usually a "Sleep(1000);" (or better a Sleep(50); inside 20 loops with a
> check for terminated) in your "Execute" procedure will be a better option.
>
> Regards,
> Stefan
>
>
>
> -----Original Message-----
> From: delphi-bounces at ns3.123.co.nz [mailto:delphi-bounces at ns3.123.co.nz] On
> Behalf Of Conor Boyd
> Sent: Thursday, 21 September 2006 2:49 p.m.
> To: nick at unica.co.nz; NZ Borland Developers Group - Delphi List
> Subject: RE: [DUG] Terminating a thread
>
> I'm not sure initially, but you may have to look at having your
> application (i.e. the main VCL thread) wait at shutdown time until your
> sub thread has successfully terminated after being told to do so.
>
> The other thing is that using Ttimer in a thread may be well dodgy, but
> that's just a hunch. Why are you having to use a timer?
>
> I haven't had to do that myself before, and I'm not sure what the timer
> is doing that's weird.
>
> Look at calling WaitForSingleObject from the main VCL thread or similar,
> and see if that helps. I can't help you with that straight off, as I
> haven't had to do that before.
>
> Good luck. If I think of anything else, I'll let you know.
>
> HTH,
>
> Conor
>
> -----Original Message-----
> From: delphi-bounces at ns3.123.co.nz [mailto:delphi-bounces at ns3.123.co.nz]
> On Behalf Of Nick Fauchelle
>
> Hmmm ok,
> So I got that going, and all seems well - my thread has set
> freeonterminate := true; when it was created.
> But when I terminate it (try) it seems to work, except when I then close
> the application I get a Access Violation error..
>
> This only happens when I have objects freeing in my destructor like so
> begin
> ProgTimer.Free;
> ADOQ1.Free;
> IdHttp.Free;
> inherited;
> end;
>
> However, if I don't have them there - my ProgTimer (TTimer) still counts
> the count, even if I terminate the thread...
> that was created like so in the creator
> ----
> ProgTimer := TTimer.Create(nil);
> ProgTimer.OnTimer := ProgTimerTimer;
> ProgTimer.Interval := 1000;
> ProgTimer.Enabled := true;
>
> Both ProgTimer : TTimer and it's OnTimer event are declared in the
> private section of my thread.
> ---
>
> Im thinking it may have something to do with the nil.
>
> So,
> If I terminate, ProgTimer.OnTimer will still fire.
> If I call ProgTimer.Free with the destructor then the timer stops
> firing, but the program access violations when I close it.
>
> :-)
>
>
>
> Conor Boyd wrote:
>
>> Once the Execute method of your thread class finishes, then your
>> thread is done working. The only way to keep a thread doing stuff is
>> to have a loop like the While not Terminated do... one I listed.
>>
>> Exit causes that loop to finish, and therefore your thread to finish.
>>
>> How the thread is freed is up to you. If you set the FreeOnTerminate
>> property to True in your constructor, then your thread will free
>> itself after the Execute method finishes, so you don't have to worry
>>
> about it.
>
>> Your TFetchData class can have a Destructor (Destroy) method just like
>>
>
>
>> any other class. That would be the place to tidy up things like
>> Tidhttp.
>>
>> Here's a rough example of the way I work with threads. This sort of
>> thread is told "go and do stuff and I don't need to hear from you
>>
> again"
>
>> sort of thing.
>>
>> TMyThread = class(Tthread);
>> Private
>> FSomeObject: Tobject;
>> Public
>> constructor Create(SomeParams: TSomeParams);
>> destructor Destroy; override;
>> procedure Execute; override;
>> End;
>>
>> Constructor TMyThread.Create(SomeParams: TSomeParams); Begin
>> inherited Create(True); // Creates thread suspended so that we can
>> set fields etc.
>>
>> FreeOnTerminate := True; // Thread will terminate itself.
>>
>> FSomeObject := Tobject.Create;
>>
>> DoSomethingWithSomeParams;
>>
>> Resume; // Now tell the thread to do its stuff in the Execute method
>>
>
>
>> End;
>>
>> Destructor TMyThread.Destroy;
>> Begin
>> FSomeObject.Free;
>> inherited;
>> End;
>>
>> Procedure TMyThread.Execute;
>> Begin
>> while not Terminated do
>> try
>> DoSomeStuff;
>>
>> if Terminated then
>> Exit; //Causes Execute method to finish, and therefore Thread
>> object to free itself
>>
>> DoSomeMoreStuff;
>> catch
>> on E:Exception
>> // Do Something with Exception
>> end;
>> End;
>>
>> HTH,
>>
>> Conor
>>
>> -----Original Message-----
>> From: Nick Fauchelle [mailto:nick at unica.co.nz]
>>
>> Thanks for the quick response.
>> Does the exit just exit the try statement (or is that break; im
>> thinking about).
>> So if there was code at the end of the thread, would it still run?
>>
>> Also, I assume anything I create
>> like
>> myHttp := TidHttp.create(nil); in the creator I should myHttp.free; in
>>
>
>
>> the OnTerminate?
>>
>> Just checking ;-)
>>
>>
>> Conor Boyd wrote:
>>
>>
>>> You're nearly there, I think.
>>>
>>> TThread has a Terminated property already.
>>>
>>> When you call the existing Terminate method on TThread, it simply
>>> sets
>>>
>>>
>>
>>
>>> the Terminated property to True.
>>>
>>> It's up to you to check the value of Terminated while your thread is
>>> processing.
>>>
>>> E.g.
>>>
>>> Procedure TFetchData.Execute;
>>> begin
>>> while not Terminated do
>>> try
>>> DoSomeStuff;
>>>
>>> if Terminated then
>>> Exit;
>>>
>>> DoSomeMoreStuff;
>>>
>>> if Terminated then
>>> Exit;
>>>
>>> DoEvenMoreStuff;
>>> catch
>>> on E: Exception do
>>> // Never let exceptions percolate out of your thread.
>>> end
>>> end;
>>>
>
> _______________________________________________
> Delphi mailing list
> Delphi at ns3.123.co.nz
> http://ns3.123.co.nz/mailman/listinfo/delphi
>
>
> _______________________________________________
> Delphi mailing list
> Delphi at ns3.123.co.nz
> http://ns3.123.co.nz/mailman/listinfo/delphi
>
>
>
More information about the Delphi
mailing list