TConnectionRunEvent = procedure(AConnection: TIdTCPConnection) of
object;
TTcpListener = class(TIdCustomThreadComponent)
private
..
FSocket: TIdTCPClient;
FOnConnectionRun: TConnectionRunEvent;
..
protected
procedure DoConnectionRun;
procedure DoRun; override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Socket: TIdTCPClient read FSocket write SetSocket;
property Active;
..
property OnConnectionRun: TConnectionRunEvent
read FOnConnectionRun
write FOnConnectionRun;
..
end;
procedure TTcpListener.DoRun;
begin
inherited;
if (FSock = nil) or (not FSock.Connected) then
begin
Stop;
end;
Synchronize(DoConnectionRun);
end;
procedure TCWTcpListener.DoConnectionRun;
begin
if Assigned(FOnConnectionRun) then
OnConnectionRun(TIdTCPConnection(FSock));
end;
...
...
What should i do for not to let it freeze my form ?
Regards,
> Is this because of i'm using Syncronize ?
Yes. By forcing your code to always run in the main VCL thread, you are
defaulting the whole purpose of using a thread in the first place.
Gambit
> After i remove the Syncronize now it's better, thanks.
> But i tried to use 5 of them. It's really slowing down
> the main thread. Is there any way to optimize it ?
Please show your actual code, including the code that you are using inside
the OnConnectionRun event handler.
Gambit
procedure TTcpListener.DoRun;
begin
inherited;
if (FSock = nil) or (not FSock.Connected) then
begin
Stop;
end;
DoConnectionRun;
end;
procedure TTcpListener.DoConnectionRun;
begin
if Assigned(FOnConnectionRun) then OnConnectionRun(TIdTCPConnection
(FSock));
end;
--- When i'm using ---
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, IdBaseComponent, IdThreadComponent, TcpListener, IdComponent,
IdTCPConnection, IdTCPClient, StdCtrls, IdTCPServer;
type
TForm1 = class(TForm)
IdTCPClient1: TIdTCPClient;
TcpListener1: TTcpListener;
TcpListener2: TTcpListener;
TcpListener3: TTcpListener;
IdTCPClient2: TIdTCPClient;
IdTCPClient3: TIdTCPClient;
IdTCPServer1: TIdTCPServer;
btnConnect: TButton;
procedure IdTCPServer1Execute(AThread: TIdPeerThread);
procedure btnConnectClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
procedure DoConnectionRun(AConnection: TIdTCPConnection);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
begin
//
end;
procedure TForm1.btnConnectClick(Sender: TObject);
begin
IdTCPClient1.Connect(1000);
IdTCPClient2.Connect(1000);
IdTCPClient3.Connect(1000);
TcpListener1.Active := True;
TcpListener2.Active := True;
TcpListener3.Active := True;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
TcpListener1.OnConnectionRun := DoConnectionRun;
TcpListener2.OnConnectionRun := DoConnectionRun;
TcpListener3.OnConnectionRun := DoConnectionRun;
end;
procedure TForm1.DoConnectionRun(AConnection: TIdTCPConnection);
begin
// here i wants to handle all of them
end;
end.
----------------------
--- Settings ---------
object IdTCPClient1: TIdTCPClient
MaxLineAction = maException
ReadTimeout = 0
Host = 'localhost'
Port = 381
Left = 144
Top = 76
end
object TcpListener1: TTcpListener
Sock = IdTCPClient1
Left = 104
Top = 76
end
object TcpListener2: TTcpListener
Sock = IdTCPClient2
Left = 104
Top = 120
end
object TcpListener3: TTcpListener
Sock = IdTCPClient3
Left = 104
Top = 164
end
object IdTCPClient2: TIdTCPClient
MaxLineAction = maException
ReadTimeout = 0
Host = 'localhost'
Port = 381
Left = 144
Top = 120
end
object IdTCPClient3: TIdTCPClient
MaxLineAction = maException
ReadTimeout = 0
Host = 'localhost'
Port = 381
Left = 144
Top = 164
end
object IdTCPServer1: TIdTCPServer
Active = True
Bindings = <>
CommandHandlers = <>
DefaultPort = 381
Greeting.NumericCode = 0
MaxConnectionReply.NumericCode = 0
OnExecute = IdTCPServer1Execute
ReplyExceptionCode = 0
ReplyTexts = <>
ReplyUnknownCommand.NumericCode = 0
Left = 316
Top = 80
end
----------------------
> TTcpListener = class(TIdCustomThreadComponent)
I would suggest deriving your component from TIdTCPClient instead and move
the thread internal to the component. For example.
TTcpListenerThread = class(TIdThread)
protected
FClient: TIdTCPClient;
procedure Run; override;
public
constructor Create(AClient: TIdTCPClient); reintroduce;
end;
TTcpListener = class(TIdTCPClient)
protected
FOnExecute: TNotifyEvent;
FThread: TTcpListenerThread;
procedure DoOnExecute;
public
destructor Destroy; override;
procedure Connect(const ATimeout: Integer = IdTimeoutDefault);
override;
procedure Disconnect; override;
published
property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
end;
constructor TTcpListenerThread.Create(AClient: TIdTCPClient);
begin
inherited Create(False);
FClient := AClient;
FreeOnTerminate := False;
end;
procedure TTcpListenerThread.Run;
begin
FClient.DoOnExecute;
FClient.CheckForDisconnect;
end;
destructor TTcpListener.Destroy;
begin
Disconnect;
inherited Destroy;
end;
procedure TTcpListener.Connect(const ATimeout: Integer =
IdTimeoutDefault);
begin
inherited Connect(ATimeout);
try
FThread := TTcpListenerThread.Create(Self);
except
on E: Exception do begin
Disconnect;
raise EIdException.Create(E.Message);
end;
end;
end;
procedure TTcpListener.Disconnect;
begin
if Assigned(FThread) then begin
FThread.Terminate;
end;
inherited Disconnect;
if Assigned(FThread) then begin
FThread.WaitFor;
FreeAndNil(FThread);
end;
end;
procedure TTcpListener.DoOnExecute;
begin
if Assigned(FOnExecute) then FOnExecute(Self);
end;
Gambit
> when i'm using this code it's slows down the GUI of
> my program and i only put 1 TcpListener on my form.
Again, please show your actual OnExecute code (which you did not do the last
time I asked you to do so).
Gambit
// --
that's all. This is the thing what i'm trying to explain. In spite of
i'm not doing anything in there, triggering an event for my component
is making my GUI slows down.
> Nothing on OnExecute section.
Then why write a component to expose OnExecute style behavior but not
actually use it?
As for the slowdown in your GUI, your lack of code in the OnExecute event is
why it is slow - the reading thread is running a tight unyielding loop that
is eating up the CPU resources because you have no code in the OnExecute
handler to slow the loop down.
Gambit
Kind Regards,