首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi 7+ Indy +多线程客户端

Delphi 7+ Indy +多线程客户端
EN

Stack Overflow用户
提问于 2012-04-27 22:21:40
回答 2查看 2.5K关注 0票数 0

我的PC连接到两个使用TCP连接发送数据的电子设备。我想开发一个Delphi程序,能够记录所有这些数据。在下面的代码中,我使用两个线程创建了两个TCPClients。我可以使用一个线程从一个设备上记录数据,但是当两个线程同时运行时,应用程序就会冻结。我没有在Delphi中编程的经验,如果有太多的错误,很抱歉…我正在使用Delphi 7。我可以做些什么来避免冻结应用程序?

提前感谢

代码语言:javascript
复制
//************************************************************************//
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.
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-27 23:24:30

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

代码语言:javascript
复制
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)则开始TCP1.Terminate;TCP1.WaitFor;FreeAndNil(TCP1);end;end;

代码语言:javascript
复制
procedure TForm1.ButtonConnection2Click(Sender: TObject);

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

代码语言:javascript
复制
procedure TForm1.ButtonDisconnection2Click(Sender: TObject);
begin
  if (TCP2 <> nil) then
  begin
    TCP2.Terminate;
    TCP2.WaitFor;
    FreeAndNil(TCP2);
  end;
end;
票数 1
EN

Stack Overflow用户

发布于 2012-04-27 22:26:55

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

提示:

如果您想使用线程与多个不同的客户端进行通信,请不要将TidTCPClients放在表单上。这是不灵活的,因为每次您想要添加一个新的客户端时,您必须将另一个实例放到表单上并重新构建。这也会让你的应用程序干净利落地关闭,我向你保证,这是你不会想要的。

在TThread派生函数或“Execute”方法的顶部动态创建一个TidTCPClient实例。

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

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

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10352409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档