0

私のPCは、TCP接続を使用してデータを送信する2つの電子デバイスに接続されています。このすべてのデータをログに記録できるDelphiプログラムを開発したいと思います。次のコードでは、2つのスレッドを使用して2つのTCPClientを作成します。1つのスレッドを使用して1つのデバイスからデータをログに記録できますが、2つのスレッドを実行すると、アプリケーションがフリーズします。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.
4

2 に答える 2

1

同じことを行う2つの別々のスレッドを作成する必要はありません。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);

begin if(TCP1 <> nil)then begin 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;
于 2012-04-27T15:24:30.240 に答える
0

TThreadConn2 .Executeでは、全体的な設計(おそらく時間内に修正される可能性がありますが、さらに助けが必要です)とは別に、Form1を呼び出します。IdTCPClient1.CurrentReadBuffer

ヒント:

スレッドを使用して複数の異なるクライアントと通信する場合は、TidTCPClientsをフォームに配置しないでください。新しいクライアントを追加するたびに、別のインスタンスをフォームに追加して再構築する必要があるため、これは柔軟性がありません。また、アプリをクリーンにシャットダウンするために多くの余分な作業が必要になりますが、これはあなたが望まないことです。

TThreadの子孫コンストラクターまたは「Execute」メソッドの先頭にTidTCPClientインスタンスを動的に作成します。

クライアント接続ごとにインスタンス化できる1つのクラスを宣言してみてください。これにより、コードをコピーして貼り付けたり、編集したり、間違えたりする必要がなくなります。

ああ-今のところ、スレッドを終了しようとしないでください。実際、永遠に、スレッドを終了しようとしないでください。実行では、成功するまでconnect()をループし、ループ内で読み取り、ログへの書き込みを行います(スレッドセーフな方法で)。それを永遠にやりなさい。ロギングを停止したい場合は、「ログに記録しない」ブール値を設定して、スレッドが引き続き実行されるようにしますが、ロガーをわざわざ呼び出さないようにします。繰り返しますが、スレッドを終了しようとしないでください。

週末にチャンスがあれば、簡単な例を示します。1つのフォーム、2つのペアのホスト名/ポート用の4つのTEdit、およびサーバーとの間でデータを送受信するための2つのTMemoです。

于 2012-04-27T14:26:55.107 に答える