【问题标题】:Delphi 7 + Indy + Multithread clientsDelphi 7 + Indy + 多线程客户端
【发布时间】:2012-04-27 14:21:39
【问题描述】:

我的电脑连接到两个使用 TCP 连接发送数据的电子设备。我想开发一个能够记录所有这些数据的 Delphi 程序。在下面的代码中,我使用两个线程创建了两个 TCPClients。我可以使用一个线程从一台设备记录数据,但是当两个线程正在运行时,应用程序会冻结。我没有在 Delphi 中编程的经验,如果有太多错误,请见谅...我使用的是 Delphi 7。我该怎么做才能避免冻结应用程序?

提前致谢

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

【问题讨论】:

    标签: multithreading delphi client-server delphi-7 indy


    【解决方案1】:

    您不需要创建两个单独的线程来做同样的事情。创建一个类,然后实例化它的多个副本。试试这个:

    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.终止; TCP1.等待; 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;
    

    【讨论】:

    • 非常感谢,您的代码对我很有帮助。我希望它对其他人也有用。
    【解决方案2】:

    除了整体设计(您可能会及时修复,可能需要更多帮助)之外,在 TThreadConn2.Execute 中,您调用 Form1.IdTCPClient1。当前读取缓冲区。

    提示:

    如果您想使用线程与多个不同的客户端进行通信,请不要将 TidTCPClients 插入表单。这是不灵活的,因为每次您想要添加新客户端时,您都必须将另一个实例插入表单并重新构建。它还需要做很多额外的工作才能让您的应用干净地关闭,我向您保证,您不会想要的。

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

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

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

    如果我周末有机会,我会做一个简单的例子 - 一个表单,四个 TEdits 用于两对主机名/端口和两个 TMemos,用于向服务器发送数据并显示来自服务器的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      相关资源
      最近更新 更多