繁体   English   中英

Delphi 7 + Indy +多线程客户端

[英]Delphi 7 + Indy + Multithread clients

我的PC已连接到两个使用TCP连接发送数据的电子设备。 我想开发一个能够记录所有这些数据的Delphi程序。 在下面的代码中,我使用两个线程创建两个TCPClient。 我可以使用一个线程从一台设备记录数据,但是当运行两个线程时,应用程序冻结。 我没有使用Delphi编程的经验,如果有太多错误,抱歉...我正在使用Delphi7。如何避免冻结该应用程序?

提前致谢

//************************************************************************//
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.

您不需要创建两个单独的线程来执行相同的操作。 创建一个类,然后实例化它的多个副本。 尝试以下方法:

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);

如果(TCP1 <> nil)开始,则开始TCP1.Terminate; TCP1.WaitFor; FreeAndNil(TCP1); 结束; 结束;

procedure TForm1.ButtonConnection2Click(Sender: TObject);

开始TCP2:= TThreadConn.Create(IdTCPClient2); 结束;

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

除了总体设计(您可能会及时修复,也许需要更多帮助)之外,在TThreadConn2中 。执行时,您调用Form1。 IdTCPClient1 .CurrentReadBuffer。

提示:

如果要使用线程与多个不同的客户端进行通信,请不要将TidTCPClients插入表单。 这是不灵活的,因为每次您要添加新客户端时,都必须将另一个实例插入到表单中并进行重建。 它还使您需要进行大量额外的工作才能完全关闭应用程序,我向您保证,您将不希望这样做。

在TThread的后代ctor或“ Execute”方法的顶部动态创建一个TidTCPClient实例。

尝试声明一个可以为每个客户端连接实例化的类,这样您就不必复制/粘贴代码,对其进行编辑并可以将其弄错。

哦-现在,不要尝试终止线程。 实际上,永远不要尝试终止线程。 在execute中,围绕connect()循环直到成功,然后循环读取内容,写入日志(以线程安全的方式)。 永远做到这一点。 如果您必须停止记录,请设置一个“不记录”布尔值,以便线程仍在运行,但根本不会打扰记录器。 再说一遍-不要试图终止线程。

如果周末有机会,我将举一个简单的例子-一种形式,两个主机名/端口对的四个TEdit和两个TMemo,用于向服务器发送数据和从服务器显示数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM