[英]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.