Board index » delphi » TIdAntiFreeze question

TIdAntiFreeze question

In my program, I build a new component class (not form) A and a new thread
class B, and there are a TIdTCPConnection in B. B is created in A and then
use TIdTCPConnection to transfer a big file in B, but my application
freezed.
Of course, I know TIdAntiFreeze can solve this, but I don't know where can I
add this TIdAntiFreeze. I tested add it in A, but same problem. how can I
solve it?

Thanks

 

Re:TIdAntiFreeze question


Quote
David <dav...@yeah.net> wrote in message

news:3e6024e5@newsgroups.borland.com...

Quote
> In my program, I build a new component class (not form) A and a new
thread
> class B, and there are a TIdTCPConnection in B. B is created in A
and then
> use TIdTCPConnection to transfer a big file in B, but my
application
> freezed.
> Of course, I know TIdAntiFreeze can solve this, but I don't know
where can I
> add this TIdAntiFreeze. I tested add it in A, but same problem. how
can I
> solve it?

Fix your bug :)

Used properly, TidTCPClient works reall well in a thread.  The main
thread does not know anything is going on.  If your app. is freezing
then you are doing something wrong.  Can you post some code?

Rgds,
Martin

PS.  Do you use 'synchronize' anywhere?  If so, that would be my
first suspect....

Re:TIdAntiFreeze question


Thank you very much for your response!

My source code is as below:

  TTask = class(TComponent)
  private
    FTaskID: Integer;
    FSendThread: TSendThread;
.
.
.
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure Execute;
    procedure Stop;
  published
.
.
.
 end;

  TSendThread = class(TThread)
  private
    fThdID: Integer;
    ID: Integer;
    fDeliveryClient: TIdTCPClient;
    FAntiFreeze: TIdAntiFreeze;
  public
    constructor Create(GID: Integer); virtual;
    destructor Destroy;  override;
    procedure Execute; override;
    procedure Abort;
    procedure SendFile;
  end;

.
.
.

procedure TMainForm.AddTask;
var
  Task: TTask;
begin
.
.
.
  Task:=TTask.Create(self);
.
.
.
  Task.SendFile;
.
.
.
end;
.
.
.
constructor TTask.Create(AOwner: TComponent);
begin
 inherited;
 FAntiFreeze:=TIdAntiFreeze.Create(self);
 FAntiFreeze.ApplicationHasPriority:=true;
 FAntiFreeze.OnlyWhenIdle:=false;
 FAntiFreeze.IdleTimeOut:=250;
 FAntiFreeze.Active:=true;
 FAntiFreeze.Process;
end;
.
.
.
procedure TTask.SendFile;
var
  SendThread: TSendThread;
begin
.
.
.
  SendThread:=TSendThread.Create(ID);
.
//Define other properties of Thread
.
  SendThread.Resume;
.
.
.
end;
.
.
.
constructor  TSendThread.Create(GID: Integer);
begin
  inherited Create(True);
  ID:=GID;
  fDeliveryClient:=nil;
  FAntiFreeze:= TIdAntiFreeze.Create(nil);
  FAntiFreeze.ApplicationHasPriority:=true;
  FAntiFreeze.OnlyWhenIdle:=true;
  FAntiFreeze.IdleTimeOut:=250;
  FAntiFreeze.Active:=true;
  FAntiFreeze.Process;

  FreeOnTerminate:=true;
end;
.
.
.
procedure TSendThread.Execute;
begin
  Synchronize(SendFile);
end;
.
.
.
procedure TSendThread.SendFile
var
  //define some vars
begin
.
//Prepare to send file
.
  FileStream:=TMemoryStream.Create;
  FileStream.LoadFromFile(Filename);
  fDeliveryClient.WriteStream(FileStream);
  FreeandNil(FileStream)
.
.
.
end;

Because my source code is very long, so I post the simple structure, I wish
it's clear.

When I run this program, application will freeze at the line:
  fDeliveryClient.WriteStream(FileStream);
but the transferring is still processed even it has freezed. When transfer
complete, application will active again. I don't know why. Can you help me?

Thanks

Quote
"Martin James" <mjames_fal...@dial.pipex.com> wrote in message

news:3e60751a@newsgroups.borland.com...
Quote

> David <dav...@yeah.net> wrote in message
> news:3e6024e5@newsgroups.borland.com...
> > In my program, I build a new component class (not form) A and a new
> thread
> > class B, and there are a TIdTCPConnection in B. B is created in A
> and then
> > use TIdTCPConnection to transfer a big file in B, but my
> application
> > freezed.
> > Of course, I know TIdAntiFreeze can solve this, but I don't know
> where can I
> > add this TIdAntiFreeze. I tested add it in A, but same problem. how
> can I
> > solve it?

> Fix your bug :)

> Used properly, TidTCPClient works reall well in a thread.  The main
> thread does not know anything is going on.  If your app. is freezing
> then you are doing something wrong.  Can you post some code?

> Rgds,
> Martin

> PS.  Do you use 'synchronize' anywhere?  If so, that would be my
> first suspect....

Re:TIdAntiFreeze question


Quote
On Sat, 1 Mar 2003 18:28:08 +0800, "David" <dav...@yeah.net> wrote:
>procedure TSendThread.Execute;
>begin
>  Synchronize(SendFile);
>end;

This line is nonsense.
The purpose of a thread is, to execute code parallel to other threads
(esp. the main thread).
The purpose of synchronize is, to run code that belongs to a
sub-thread in the context of the main-thread.
 So, in your situation, all that the thread does (sending a file) is
executed via synchronize and therefore the whole SendFile procedure
will run as if called by the main thread - that's why your main-thread
(and therefore your main form) freezes during the send.
Leave out the Synchronize, so that SendFile is actually run in the
context of the sub thread (as it was intended I guess) and you don't
need AntiFreeze at all.
AntiFreeze must be used in the main thread and it only works when the
blocking call (sending or receiving data) is made in the main-thread
as well.

Since you already use threads, you don't need AntiFreeze at all...

Andy

Re:TIdAntiFreeze question


Thanks Andy,

But I have try to change this procedure into:

procedure TSendThread.Execute;
begin
   SendFile;
end;

and run it again, I get the same problem. I think it's not because of
Synchronize, if I create and run this TSendThread in MailForm directly, it
runs better. And if I add a OnWorking event for fDeliveryClient, and add
line:

Application.ProcessMessage;

in this event, application will not freeze as before, but it is also not
good enough. Any other ideas?

Thanks

Quote
"Andy M." <[no-spam]andy.mail...@gmx.net> wrote in message

news:mbj16vsao021bbqqr0dlljvjmh93e3opdq@4ax.com...
Quote
> On Sat, 1 Mar 2003 18:28:08 +0800, "David" <dav...@yeah.net> wrote:

> >procedure TSendThread.Execute;
> >begin
> >  Synchronize(SendFile);
> >end;

> This line is nonsense.
> The purpose of a thread is, to execute code parallel to other threads
> (esp. the main thread).
> The purpose of synchronize is, to run code that belongs to a
> sub-thread in the context of the main-thread.
>  So, in your situation, all that the thread does (sending a file) is
> executed via synchronize and therefore the whole SendFile procedure
> will run as if called by the main thread - that's why your main-thread
> (and therefore your main form) freezes during the send.
> Leave out the Synchronize, so that SendFile is actually run in the
> context of the sub thread (as it was intended I guess) and you don't
> need AntiFreeze at all.
> AntiFreeze must be used in the main thread and it only works when the
> blocking call (sending or receiving data) is made in the main-thread
> as well.

> Since you already use threads, you don't need AntiFreeze at all...

> Andy

Re:TIdAntiFreeze question


Quote
> procedure TSendThread.Execute;
> begin
>    SendFile;
> end;

> and run it again, I get the same problem. I think it's not because
of
> Synchronize,

I bet it is.

I|f you have any synchronise calls in your thread, I'm 99% sure that
you still have that you still have the problem that Andy described -
you are synchronizing the SendFile somehow, making your app. perform
worse that if it was single-threaded.

Hint: take *all* the 'synchronize' calls out of your code.  If you
want to update some VCL controls, pass the HWND handle of your form
to the thread in the constructor & use postMesage to send data to a
message-handler in the main thread.

Synchronize  has some issues.  It's not always bad, but it's very
easy to misuse, as is 'application.processMessages'.

Rgds,
Martin

Re:TIdAntiFreeze question


If you still have problems with freezing, perhaps you could post some
cut-down app that demonstrates the problem.  Andy or I would spot the
problem quickly, I think.

Rgds,
Martin

Re:TIdAntiFreeze question


Thanks for all, I have solved this problem.

Quote
"David" <dav...@yeah.net> wrote in message

news:3e6174b3$1@newsgroups.borland.com...
Quote
> Thanks Andy,

> But I have try to change this procedure into:

> procedure TSendThread.Execute;
> begin
>    SendFile;
> end;

> and run it again, I get the same problem. I think it's not because of
> Synchronize, if I create and run this TSendThread in MailForm directly, it
> runs better. And if I add a OnWorking event for fDeliveryClient, and add
> line:

> Application.ProcessMessage;

> in this event, application will not freeze as before, but it is also not
> good enough. Any other ideas?

> Thanks

> "Andy M." <[no-spam]andy.mail...@gmx.net> wrote in message
> news:mbj16vsao021bbqqr0dlljvjmh93e3opdq@4ax.com...
> > On Sat, 1 Mar 2003 18:28:08 +0800, "David" <dav...@yeah.net> wrote:

> > >procedure TSendThread.Execute;
> > >begin
> > >  Synchronize(SendFile);
> > >end;

> > This line is nonsense.
> > The purpose of a thread is, to execute code parallel to other threads
> > (esp. the main thread).
> > The purpose of synchronize is, to run code that belongs to a
> > sub-thread in the context of the main-thread.
> >  So, in your situation, all that the thread does (sending a file) is
> > executed via synchronize and therefore the whole SendFile procedure
> > will run as if called by the main thread - that's why your main-thread
> > (and therefore your main form) freezes during the send.
> > Leave out the Synchronize, so that SendFile is actually run in the
> > context of the sub thread (as it was intended I guess) and you don't
> > need AntiFreeze at all.
> > AntiFreeze must be used in the main thread and it only works when the
> > blocking call (sending or receiving data) is made in the main-thread
> > as well.

> > Since you already use threads, you don't need AntiFreeze at all...

> > Andy

Re:TIdAntiFreeze question


Thank you very much, Martin.

The reason of this problem is using TThread.Execute to execute the thread.
Now I change it to TThread.Resume, application works fine.

Quote
"Martin James" <mjames_fal...@dial.pipex.com> wrote in message

news:3e61bbda@newsgroups.borland.com...
Quote
> If you still have problems with freezing, perhaps you could post some
> cut-down app that demonstrates the problem.  Andy or I would spot the
> problem quickly, I think.

> Rgds,
> Martin

Re:TIdAntiFreeze question


Martin, now I have another question.

How can I handle the THREAD CREATION ERROR and solve it when my application
create threads?

Thanks

Quote
"David" <dav...@yeah.net> wrote in message

news:3e61f576@newsgroups.borland.com...
Quote
> Thank you very much, Martin.

> The reason of this problem is using TThread.Execute to execute the thread.
> Now I change it to TThread.Resume, application works fine.

> "Martin James" <mjames_fal...@dial.pipex.com> wrote in message
> news:3e61bbda@newsgroups.borland.com...
> > If you still have problems with freezing, perhaps you could post some
> > cut-down app that demonstrates the problem.  Andy or I would spot the
> > problem quickly, I think.

> > Rgds,
> > Martin

Re:TIdAntiFreeze question


Quote
David <dav...@yeah.net> wrote in message

news:3e61f633@newsgroups.borland.com...

Quote
> Martin, now I have another question.

> How can I handle the THREAD CREATION ERROR and solve it when my
application
> create threads?

Dunno - never seen it!

I create Tthread descendants like this, passing any parameters needed
in the constructor:

  TworkThread=class(TThread)
  private
    inMess:TworkMessage;
    myThreadNum:integer;
    returnForm:HWND;
    workMail:Tmailbox;
  protected
    procedure execute; override;
  public
    constructor
create(threadNum:integer;returnHandle:HWND;inMailbox:Tmailbox);
  end;

constructor
TworkThread.create(threadNum:integer;returnHandle:HWND;inMailbox:Tmai
lbox);
begin
  inherited create(true);
  freeOnTerminate:=true;
  myThreadNum:=threadNum;
  returnForm:=returnHandle;
  workMail:=inMailbox;
  resume;
end;

The whole constructor runs in the contect of the caller and the
thread execute method is made ready at the end, when it is resumed,
having had all its parameters stored away in fields.  The OS appears
usually to run it immediately, preempting the main thread, (unless
you change priorities), though it should not matter to your app.

Rgds,
Martin

Other Threads