我的电脑连接到两个使用TCP连接发送数据的电子设备。我想开发一个能够记录所有这些数据的Delphi程序。在下面的代码中,我使用两个线程创建两个TCPClient。我能够使用一个线程从一个设备记录数据,但是当两个线程运行时,应用程序冻结。我没有使用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.
答案 0 :(得分: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);
开始 if(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;
答案 1 :(得分:0)
除了整体设计(你可能会及时修复,也许还有一些帮助),在 TThreadConn2 .Execute中,你可以调用Form1。 IdTCPClient1 。 CurrentReadBuffer。
提示:
如果要使用线程与多个不同的客户端进行通信,请不要将TidTCPClient存储到表单上。这是不灵活的,因为每次要添加新客户端时,都必须将另一个实例放到表单上并重建。这也让你的应用程序干净利落地完成了很多额外的工作,我向你保证,你不会想要它。
在TThread后代ctor或“Execute”方法的顶部动态创建TidTCPClient实例。
尝试并声明一个可以为每个客户端连接实例化的类,这样就不必复制/粘贴代码,编辑代码并将其弄错
哦 - 现在,不要尝试终止线程。事实上,永远不要尝试终止线程。在执行中,循环connect()直到成功,然后在循环中读取东西,写入日志,(以线程安全的方式)。永远这样做。如果您想要停止日志记录,请设置一个'do not log'布尔值,以便线程仍然运行但只是不打扰调用记录器。再次 - 不要试图终止线程。
如果我有机会在周末,我会做一个简单的例子 - 一个表格,四个TEdits用于两对主机名/端口,两个TMemos用于向服务器发送数据并显示数据。