2012-04-27 135 views
0

我的電腦連接到兩個使用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. 

回答

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); 

開始 如果(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

0

除了整體設計,(你可能會在固定時間,可能與一些更多的幫助),在TThreadConn2 .Execute,你叫Form1中。 IdTCPClient1 .CurrentReadBuffer。

提示:

如果你想使用線程與幾個不同的客戶進行溝通,不plonk的TidTCPClients到形式。這是不靈活的,因爲每當你想添加一個新的客戶端時,你必須將另一個實例放到窗體上並重建。它也使得你的應用程序能夠乾淨地關閉很多額外的工作,我向你保證,你不會想要的。

在TThread後代ctor或'Execute'方法的頂部動態創建一個TidTCPClient實例。

嘗試,並聲明一個類可以實例爲每個客戶端連接,所以你不必複製/粘貼代碼,編輯並得到它錯

哦 - 現在,請不要嘗試並根本終止線程。事實上,永遠不要試圖終止線程。在執行中,循環connect()直到成功,然後在循環中讀取東西,寫入日誌(以線程安全的方式)。永遠這樣做。如果你想停止日誌記錄,設置一個'不要日誌'布爾值,以便線程仍然運行,但根本不打擾調用記錄器。再次 - 不要試圖終止線程。

如果我在週末有機會,我會做一個簡單的例子 - 一個表單,兩個雙主機名/端口的四個TEdits和兩個TMemos向服務器發送數據和顯示數據。