Delphi 7 + Indy +多线程客户端

问题描述:

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

在此先感谢

//************************************************************************// 
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 <>零),那么 开始 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; 
+0

非常感谢,您的代码对我非常有帮助。我希望它对其他人也有用。 – user1361263 2012-05-02 12:10:07

除了整体设计,(你可能会在固定时间,可能与一些更多的帮助),在TThreadConn2 .Execute,你叫Form1中。 IdTCPClient1 .CurrentReadBuffer。

提示:

如果你想使用线程与几个不同的客户进行沟通,不plonk的TidTCPClients到形式。这是不灵活的,因为每当你想添加一个新的客户端时,你必须将另一个实例放到窗体上并重建。它也使得你的应用程序能够干净地关闭很多额外的工作,我向你保证,你不会想要的。

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

尝试,并声明一个类可以实例为每个客户端连接,所以你不必复制/粘贴代码,编辑并得到它错

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

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