Einzelnen Beitrag anzeigen

ghubi01

Registriert seit: 18. Nov 2017
133 Beiträge
 
Delphi 12 Athens
 
#3

AW: Indy TCPClient Lesethread sicher beenden

  Alt 20. Nov 2017, 15:15
Hallo,

das Thema hat mir keine Ruhe gelassen, da ich selber dieses Problem in eigenen Projekten habe bzw. hatte.
Eine Exception trat in meinen Programmen aber nur auf, wenn ich es aus der IDE mit dem Debugger gestartet habe.

Als kleines Beispiel habe ich Deine Thread-Klasse etwas umgebaut. Die Events TForm1.ClientConnected und TForm1.ClientDisconnected
habe ich ganz rausgenommen. Der Schreibvorgang Client.IOHandler.WriteLn(tcpStringSend); liegt jetzt im Hauptthread von Form1.
Vielleicht hilft das ein bischen.

Delphi-Quellcode:

interface

const
  WM_CLIENTANSWER = WM_USER+1;

//*** TReadingThread
type
  TReadingThread= class(TThread)
  private
    FOutStr: string;
    FClient: TIdTCPClient;
    procedure HandleInput;
  protected
    procedure Execute; override;
  public
    constructor Create(ATCPClient: TIdTCPClient);
  end;

//*** TForm1

type
  TForm1 = class(TForm)
    //...
  private
    { Private-Deklarationen }
    procedure AnswerEvent(var Msg: TMessage); Message WM_CLIENTANSWER;
    //...
  end;

//...


implementation

constructor TReadingThread.Create(AClient: TIdTCPClient);
 begin
   TLog.AddMsg('DEBUG: TReadingThread.Create');
   FClient := AClient;
   inherited Create(False);
 end;

procedure TReadingThread.HandleInput;
var
   cmd: string;
begin
  if FClient.Connected then
  begin
    try
      cmd:=FClient.IOHandler.ReadLn(#3);
      TLog.AddMsg('DEBUG: TReadingThread.Execute. Cmd: ' + cmd);
    except
      on E: Exception do
      begin
        cmd:=E.Message;
        TLog.AddMsg('DEBUG: TReadingThread.Execute. Err: ' + cmd);
      end;
    end;

    PostMessage(Form1.Handle,WM_CLIENTANSWER,integer(@cmd),0);

  end else Terminate;
end;

procedure TReadingThread.Execute;
begin
  while not Terminated do
  begin
    HandleInput;
  end;
end;

procedure TForm1.AnswerEvent(var Msg: TMessage); //Antwort vom Thread übernehmen
var
  CmdStr, tcpStringSend: String;
  P: ^string;
begin
  P:=Pointer(Msg.WParam);
  CmdStr:=P^;
  TelegramNr := copy(CmdStr, 1, 2);
  tcpStringSend := #2 + TelegramNr + '001050QU' + #3;

  if Client.Connected then Client.IOHandler.WriteLn(tcpStringSend); //Nur schreiben, wenn Verbindung noch besteht!
end;

procedure TForm1.Button1Click(Sender: TObject);
 var
   Host: string;
   Port: Integer;
 begin
   Host := '192.168.100.74';
   Port := StrToInt('4100');

   Client.Host := Host;
   Client.Port := Port;

   try
     Client.Connect;
   except
     on E: Exception do
       TLog.AddMsg('Error: ' + E.Message);
   end;

   if Client.Connected then rt:=TReadingThread.Create(Client);

 end;

procedure TForm1.Button2Click(Sender: TObject); //Disconnect reicht; der Thread terminiert sich selbst!
begin
   Client.IOHandler.InputBuffer.Clear;

  try
    Client.Disconnect;
  except
    on E: Exception do
       TLog.AddMsg('Error: ' + E.Message);
  end;
end;

Geändert von ghubi01 (20. Nov 2017 um 15:17 Uhr)
  Mit Zitat antworten Zitat