Search code examples
multithreadingdelphiclient-serverdelphi-7indy

Delphi 7 + Indy + Multithread clients


My PC is connected to two electronic devices that send data using a TCP connection. I would like to develop a Delphi program able to log all this data. In the following code I create two TCPClients using two threads. I am able to log data from one device using one thread, but when two threads are runnning the application freezes. I don´t have experience programming in Delphi, sorry if there are too many mistakes... I am using Delphi 7. What can I do to avoid freezing the app?

Thanks in advance

//************************************************************************//
type TThreadConn1 = class(TThread)
    private
    protected
        procedure Execute; override;
    end;

type TThreadConn2 = class(TThread)
    private
    protected
        procedure Execute; override;
    end;


var
    Form1: TForm1;
    TCP1: TThreadConn1;
    TCP2: TThreadConn2;
    flag1: bool;
    flag2: bool;


implementation
{$R *.dfm}

//******************************Connection 1******************************//
procedure TThreadConn1.Execute;  //Connect+loop read buffer+disconnect
begin
    Form1.IdTCPClient1.Connect;  
    While flag1 = false do   
        Form1.IdTCPClient1.CurrentReadBuffer;
    Form1.IdTCPClient1.Disconnect;
end; 

procedure TForm1.ButtonConnection1Click(Sender: TObject);
begin
    flag1:=false;
    TCP1 := TThreadConn1.Create(false);  //Launch thread 
end;

procedure TForm1.ButtonDisconnection1Click(Sender: TObject);
begin
    flag1:=true;
    if (TCP1.Terminated = false) then
        TCP1.Terminate;   //Is it ok to finish this way a thread?
    end;

//******************************Connection2******************************//
procedure TThreadConn2.Execute;  //Connect+loop read buffer+disconnect
begin
    Form1.IdTCPClient2.Connect;
    While flag2 = false do   
        Form1.IdTCPClient1.CurrentReadBuffer;
    Form1.IdTCPClient2.Disconnect;
end; { of procedure }

procedure TForm1.ButtonConnection2Click(Sender: TObject);
begin
    flag2:=false;
    TCP2 := TThreadConn2.Create(false);
end;

procedure TForm1.ButtonDisconnection2Click(Sender: TObject);
begin
    flag2:=true;
    if (TCP2.Terminated = false) then
        TCP2.Terminate;
end;
end.

Solution

  • You don't need to create two separate threads that do the same thing. Create one class and then instantiate multiple copies of it. Try this instead:

    type
      TThreadConn = class(TThread)
      private
        FClient: TIdTCPClient;
      protected
        procedure Execute; override;
      public
        constructor Create(AClient: TIdTCPClient);
      end;
    
    var
      TCP1: TThreadConn = nil;
      TCP2: TThreadConn = nil;
    
    constructor TThreadConn.Create(AClient: TIdTCPClient);
    begin
      inherited Create(False);
      FClient := AClient;
    end;
    
    procedure TThreadConn.Execute;
    begin
      FClient.Connect;  
      try
        while Terminated = false do   
          FClient.CurrentReadBuffer;
      finally
        FClient.Disconnect;
      end;
    end; 
    
    procedure TForm1.ButtonConnection1Click(Sender: TObject);
    begin
      TCP1 := TThreadConn.Create(TIdTCPClient1);
    end;
    
    procedure TForm1.ButtonDisconnection1Click(Sender: TObject);
    

    begin if (TCP1 <> nil) then begin TCP1.Terminate; TCP1.WaitFor; FreeAndNil(TCP1); end; end;

    procedure TForm1.ButtonConnection2Click(Sender: TObject);
    

    begin TCP2 := TThreadConn.Create(IdTCPClient2); end;

    procedure TForm1.ButtonDisconnection2Click(Sender: TObject);
    begin
      if (TCP2 <> nil) then
      begin
        TCP2.Terminate;
        TCP2.WaitFor;
        FreeAndNil(TCP2);
      end;
    end;