Delphi-PRAXiS
Seite 1 von 2  1 2   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Thread stürzt ab Indy TCPIP Client (https://www.delphipraxis.net/183433-thread-stuerzt-ab-indy-tcpip-client.html)

Barthiboy 9. Jan 2015 07:06

Thread stürzt ab Indy TCPIP Client
 
Hallo zusammen.

Folgende Konstellation:
Siemens Steuerung S7 == Server, selbst geschrieben SCL mit Simatic Manager
Win7 Prof PC == Client, selbst geschrieben Delphi XE5
Kommunikation über TCPIP

Folgendes Problem im Client:
Mein Client kann mit verschiedenen SPSen kommunizieren.
Hierfür erzeuge ich pro SPS einen Thread, in welchem ich mit der Indykomponente über TCP/IP kommuniziere.
Das funktioniert soweit auch ganz gut.
Wenn ich die Steuerung Neustarte oder Reset betätige wird die Verbindung vom Server geschlossen.
Wenn die Steuerung allerdings ausgeschaltet wird, ist der Server ja nicht mehr da und die Verbindung bricht ab.
Dabei stürzt der Kommunikationsthread gleich komplett ab.
Hier ein Auszug aus dem Logger:

07:38:38 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:38:40 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:38:49 SPS2Client : Zeitüberschreitung beim Lesen.
07:38:51 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:38:52 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:38:53 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:38:55 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:38:56 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:38:59 SPS2Client : Die Verbindung wurde erfolgreich geschlossen.
07:39:05 SPS2Client : Socket-Fehler # 10053Software verursachte einen Verbindungsabbruch.

Alle Einträge außer der Letzte sind druch Neustart oder Reset entstanden.
Danach verbindet der Thread auch gleich wieder neu.
Beim letzen Eintrag schmiert der Thread komplett ab.
Ist im Thread-Status Fenster auch nicht mehr zu sehen.

Weiß jemand woran das liegen kann. Bzw. wie ich nach dem Fehler suchen kann?
Eigentlich werden alle Exceptions mit geloggt.

Vielen Dank schon mal.
Hier die Execute procedure
Delphi-Quellcode:
procedure TKommSPS.Execute;
var
  freq: Int64;
  startTime: Int64;
  endTime: Int64;
  Time : Int64;
  i : Integer;
begin
  QueryPerformanceFrequency(freq);
  // Kommunikations-Thread Hauptschleife
  while not Terminated do begin
    while FKommEnable and not Terminated do begin
      try
        // Wenn nicht verbunden
        if (not FIdTCPClient.Connected) and not Terminated then begin
          if FLogger <> nil then begin
            FLogger.LogMessage(TimeToStr(now) + ' SPS' + IntToStr(SPS) + 'Client : ' + 'Connecting');
          end;
          FIdTCPClient.Connect;
        end;
        // Wenn verbunden
        if FIdTCPClient.Connected and not Terminated then begin
          FKommAktiv := true;
          // Zeitmessung just for performancetest
          QueryPerformanceCounter(endTime);
          Time := endTime - startTime;
          QueryPerformanceCounter(startTime);

          // Priority Aufträge abarbeiten
          if FPriorityKommAuftrag <> nil then begin
            for i := 0 to length(FPriorityKommAuftrag) - 1 do begin
              Auftragsenden(FPriorityKommAuftrag[i].Form, FPriorityKommAuftrag[i].Auftrag, FPriorityKommAuftrag[i].RdWrt);
              Auftragempfangen(FPriorityKommAuftrag[i].Form, FPriorityKommAuftrag[i].Auftrag, FPriorityKommAuftrag[i].RdWrt);
            end;
          end;
          // User Aufträge abarbeiten
          if (length(FKommAuftrag) > 0) then begin
            // Ersten Auftrag in der Liste senden
            // Useraufträge
            Auftragsenden(FKommAuftrag[0].Form, FKommAuftrag[0].Auftrag , FKommAuftrag[0].RdWrt);
            Auftragempfangen(FKommAuftrag[0].Form, FKommAuftrag[0].Auftrag , FKommAuftrag[0].RdWrt);
            Auftragverwalten();
          end;
          // Kommunikation visualisieren
          Synchronize(Btn_Komm_toggle);
        end;
      except
        on E: Exception do begin
          Logger.LogErrorMessage(TimeToStr(now) + ' SPS' + IntToStr(SPS) + 'Client : ' + E.ToString);
          if Assigned(FIdTCPClient.IOHandler) then begin
            FIdTCPClient.IOHandler.InputBuffer.Clear;
          end;
          if FIdTCPClient.Connected then begin
            FIdTCPClient.Disconnect;
          end;
          Synchronize(Btn_Komm_error);
        end;
      end;

      // Nur pausieren wenn nichts zu tun oder disconnected
      if not FIdTCPClient.Connected and not Terminated then begin
        Sleep(500);
      end;
      // Wenn Programm beendet werden soll
      if Terminated then begin
      // Wenn noch eine Verbindung besteht, Verbindung trennen
        if FIdTCPClient.Connected then begin
          FIdTCPClient.Disconnect;
          Exit;
        end;
      end;
    end;
    // Kommunikation ist disabled
    FKommAktiv := false;
    Sleep(300);
  end;
  FIdTCPClient.Free;
  Sleep(0);
end;

Sir Rufo 9. Jan 2015 09:31

AW: Thread stürzt ab Indy TCPIP Client
 
Es werden eben nicht alle Exceptions geloggt, sonst würdest du eine weitere sehen. Das Thread-Objekt hat auch noch eine Exception, die du abfragen kannst, wenn der Thread sich beendet hat.

Delphi-Referenz durchsuchenSystem.Classes.TThread.FatalException

Da findest du deine Exception. Ausgelöst wird diese durch das, was du da in deinem Except-Teil veranstaltest. Der beste Kandidat dafür ist
Delphi-Quellcode:
FIdTCPClient.IOHandler.InputBuffer.Clear;
.

Das liegt daran, dass du relativ blind bei jeder Exception davon ausgehst, dass du die so behandeln kannst. Dem ist aber nicht so. Bei einer Zugriffsverletzung kannst du das so eben nicht behandeln.

Darum gibt man auch explizit die Exceptions an, die man behandeln kann. Wäre in deinem Falle irgendeine der
Delphi-Quellcode:
EIdExcetion
s. Dem Socket-Fehler kann man so eben nicht beikommen. Im Extremfall schmeisst du mit
Delphi-Quellcode:
FreeAndNil
den Tcp-Client einfach aus dem Speicher und am Anfang der Schleife erstellst du bei Bedarf den Client.

Barthiboy 9. Jan 2015 10:07

AW: Thread stürzt ab Indy TCPIP Client
 
Hallo

danke für die Antwort.
Das Ereignis OnTerminateKommSPS wird nicht ausgelöst. Ich kann die Exception als nicht abfragen oder?
Welche EIdExcetion´s muss man den abfangen, bzw. was spricht dagegen den Buffer zu clearen?
Warum führt das zu einer Exception? Über
Delphi-Quellcode:
if Assigned(FIdTCPClient.IOHandler) then begin
frage ich doch ab ob er da ist!?

Danke

Sir Rufo 9. Jan 2015 10:24

AW: Thread stürzt ab Indy TCPIP Client
 
Es gibt bei Exceptions kein "welche muss ich" sondern immer nur ein "welche kann ich" behandeln ;)

Wenn du den InputBuffer (Instanz) löschst und fragst, ob es einen IOHandler (Instanz) gibt, wie kommst du darauf, dass es auch einen InputBuffer geben muss?

So wäre es schon mal bis zum Schluss geprüft:
Delphi-Quellcode:
if { Assigned( FFoo ) and } Assigned( FFoo.IOHandler ) and Assigned( FFoo.IOHandler.InputBuffer ) then
  FFoo.IOHandler.InputBuffer.Clear;

Barthiboy 9. Jan 2015 10:39

AW: Thread stürzt ab Indy TCPIP Client
 
Also ich habe die Abfrage jetzt mal so rein.
Allerdings immer noch mit dem gleichen Effekt.
Woher weiß ich welche Exceptions ich behandeln kann?

Zitat:

Wenn du den InputBuffer (Instanz) löschst und fragst, ob es einen IOHandler (Instanz) gibt, wie kommst du darauf, dass es auch einen InputBuffer geben muss?
Ich frag doch zuerst und lösche dann, oder steh ich jetzt voll daneben!?

Edit:

Ich habe jetzt FIdTCPClient.IOHandler.InputBuffer.Clear; komplett rausgeschmissen.
Der Fehler tritt jetzt wesentlich weniger auf.
Aber bei excesivem Steuerung reset, Neuanlauf usw. bekomme ich immer noch folgende Meldung:
Socket-Fehler # 10054Die Verbindung wurde von Peer zurückgesetzt.

Also muss ich das wohl irgendwie doch noch abfangen

Barthiboy 9. Jan 2015 11:01

AW: Thread stürzt ab Indy TCPIP Client
 
ich habe hier einen ähnlichen Fall gefunden:
http://www.delphipraxis.net/163393-i...-umleiten.html

In dem letzten Eintrag steht wohl die Lösung.
Aber nachvollziehen kann ich das noch nicht.
Vor allem frage ich vorher ab ob die Verbindung überhaupt besteht.

Sir Rufo 9. Jan 2015 11:24

AW: Thread stürzt ab Indy TCPIP Client
 
Deine Execute-Methode ist irgendwie zu lang und unhandlich ... (würde ich so nie implementieren). Teile die auf, dann wird das wesentlich einfacher:

Delphi-Quellcode:
TFoo.Execute;
var
  LClient : TClient;
begin
  LClient := nil;
  try
    while not Terminated do
    try
      // Eine Client-Instanz garantieren
      if not Assigned( LClient ) then
      begin
        LClient := TClient.Create;
      end;
     
      ExecuteOnCLient( LClient );

    except
      on E: EIdSpecialException do
      begin
        // Loggen der Exception

       // Client benötigt nur einen Reset
       LClient.Reset;
      end;
      on E: EIdException do
      begin
        // Loggen der Exception
       
       // Zerstören der Client-Instanz
       FreeAndNil( LClient );
      end;
      on E: Exception do
      begin
        // Loggen der Exception
       
        raise; // Exception raisen -> der Thread wird beendet
      end;
    end;
  finally
    LClient.Free;
  end;
end;

procedure TFoo.ExecuteOnCLient( AClient : TClient );
begin
  // Hier geht es jetzt los mit der eigentlichen Verarbeitung
end;

Barthiboy 12. Jan 2015 06:09

AW: Thread stürzt ab Indy TCPIP Client
 
Danke für deine Antworten.

ich habe noch folgende Probleme:
TIdTCPClient.Reset gibt es bei mir nicht v.10.6.0.504.
EIdSpecialException gibt es bei mir nicht v.10.6.0.504. Oder ich kanns nicht finden.

Aber sonst sieht es so aus als hättest du mir viel weiter geholfen.

Sir Rufo 12. Jan 2015 08:05

AW: Thread stürzt ab Indy TCPIP Client
 
Und wo hast du
Delphi-Quellcode:
TFoo
und
Delphi-Quellcode:
TClient
gefunden?

Der Code ist nur dazu da, das Prinzip zu erläutern und keine CopyPaste Lösung. Anfangen würde ich auch zunächst auch damit, bei jeder Indy Exception
Delphi-Quellcode:
EIdException
den Client einfach aus dem Speicher zu entfernen.

Dann schaut man sich das Log an und die aufgetretenen Exceptions und prüft, bei welcher Exception man noch etwas retten könnte. Allerdings wäre es mir auch egal, denn wenn der Betrieb so gewährleistet werden kann ... who cares? Da bräuchte ich schon bessere Gründe.

Barthiboy 12. Jan 2015 08:15

AW: Thread stürzt ab Indy TCPIP Client
 
OK. Prinzip is jetzt klar.
Du hast mir viel geholfen. Vielen Dank. :-D

Die Verbindungsprobleme, die ich hervorrufen konnte sind somit alle beseitigt.
Jetzt muss ich mir nur überlegen, was ich bei einer Zugriffsverletzung usw. mache.
Aber das soll (bis jetzt) mal noch nicht dein Problem sein ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:24 Uhr.
Seite 1 von 2  1 2   

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf