簡體   English   中英

Delphi 7 + Indy +多線程客戶端

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM