Re: Thread Error in Delphi7

From: Rob Kennedy (me3_at_privacy.net)
Date: 03/25/04


Date: Thu, 25 Mar 2004 11:20:05 -0600

UkkoNoa wrote:
> There is a one unit (analog clock) component containing thread systems and
> the following two-unit own thread in my app.

What need does a clock have for downloading files from the network? I
smell feature creep.

> Implementation
> Uses Some;
>
> var SomeThread :TSome;

Some? You call your class "TSome"? Please pick a meaningful name.

> procedure TMainForm.Some1Click(Sender: TObject);
> begin
> SomeThread := TSome.Create(false);
> end;

Keep in mind that if you click the Some button twice, you will have two
TSome threads, but you'll only have a reference to the second one. The
first reference, which was stored in SomeThread, will get overwritten.
If you don't require any reference to the thread after it's been created
(and it doesn't look like you do), then you don't need to store a
reference to it. You can simply call the constructor and ignore the result:

begin
   TSome.Create(False);
end;

> Unit Someunit;
> ===========
> interface
> uses Windows,Classes,Sysutils,Forms,UrlMon,Main;
>
> type
> TSome = class(TThread)
> private
> { Private declarations }
> protected
> procedure Execute; override;
> public
> Constructor Create(CreateSuspended: Boolean);
> procedure CheckUrl;
> end;
>
> implementation
>
> Constructor TSome.Create(CreateSuspended: Boolean);
> Begin
> Inherited Create(CreateSuspended);
> FreeOnTerminate := true;

It's best not to set change the FreeOnTerminate property after the
thread has already started running. Set FreeOnTerminate *before* you
call the inherited constructor. If CreateSuspended is False, then the
thread might already be executing by the time execution reaches the
point where you set the FreeOnTerminate property. And if it's already
executing, then it's already in a position to be raising exceptions and
terminating, so there may be the possibility that you're setting
properties on a thread that's already gone.

> procedure TSome.Execute;
> begin
> Synchronize(CheckUrl);
> end;

That renders your thread totally and completely useless. The Synchronize
procedure is a blocking call. It transfers control back to the main VCL
thread and executes the procedure within that thread's context.

The *only* thing your thread does is wait for the main thread to check a
URL. You could have done that with a simple function call, not a thread.

> (******************************)
> procedure TSome.CheckUrl;
> begin
> if DownloadFromUrl(''xxxxx') then MainForm.Execute;
> Terminate;
> end;

Unless you actually check the Terminated property somewhere else in your
code, the Terminate procedure has no effect. The only time a thread
actually terminates is when its Execute method finishes running. Threads
will usually have some sort of loop in their Execute methods.

You could do this:

type
   TSome = class(TThread)
   protected
     procedure Execute; override;
   public
     constructor Create(AOnTerminate: TNotifyEvent);
     property ReturnValue;
   end;

constructor TSome.Create(AOnTerminate: TNotifyEvent);
begin
   FreeOnTerminate := True;
   OnTerminate := AOnTerminate;
   inherited Create(False);
   Priority := tpIdle;
end;

procedure TSome.Execute;
begin
   if DownloadFromURL('xxxxx') then ReturnValue := 1 else ReturnValue := 0;
end;

procedure TMainForm.Some1Click(Sender: TObject);
begin
   TSome.Create(SomeThreadTerminate);
end;

procedure TMainForm.SomeThreadTerminate(Sender: TObject);
begin
   case TSome(Sender).WaitFor of
     0: ; // DownloadFromURL failed; do nothing.
     1: Self.Execute;
     else Assert(False, 'TSome terminated with an unexpected value');
   end;
end;

-- 
Rob


Relevant Pages

  • Re: thread.Abort()
    ... > as you hang onto the reference. ... > executing code in a finally block - this can be interrupted with unknown ... > target thread is alive but before the next line of code executes a context ... > thread to actually terminate is also unbounded. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: thread.Abort()
    ... executing code in a finally block - this can be interrupted with unknown ... target thread is alive but before the next line of code executes a context ... One safe way for one thread to signal another thread to terminate is to use ... a signalling mechanism, such as a ManualResetEvent, that the calling thread ...
    (microsoft.public.dotnet.languages.csharp)
  • Delphi Trojans
    ... I have a component I have been working on that happened to reference a unit ... the controller unit for an application which instantiates a controller ... noticed that delphi was executing this code, which was logging into a server ... No longer will I download components without source code. ...
    (borland.public.delphi.non-technical)
  • Re: Prematurely garbage collection
    ... In the example below, when Invoke is being executed, the reference of the instance is available with app root - so the object is not collected until there are no more pending references. ... Executing the example given by Jon below on my machine gave the following output: ... static void Main ...
    (microsoft.public.dotnet.framework.clr)
  • Equivalent functionality to Thread.stop()?
    ... I have read through the short article why stopand others are deprecated, but the solutions offered in this article to simulate these functions are simply not usable in many situations (and the arguments why these methods get removed are void in many situations, but whatever). ... I need to terminate a thread which is executing methods which itself may take a long time to execute, so my thread is /blocked/, until these methods return. ... However, all solutions in this article use some form of repeated checking for some condition, which only works if your runmethod is executing in a while-loop. ...
    (comp.lang.java.programmer)