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; |
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.
System.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:
s. Dem Socket-Fehler kann man so eben nicht beikommen. Im Extremfall schmeisst du mit
EIdExcetion
Delphi-Quellcode:
den Tcp-Client einfach aus dem Speicher und am Anfang der Schleife erstellst du bei Bedarf den Client.
FreeAndNil
|
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:
frage ich doch ab ob er da ist!?
if Assigned(FIdTCPClient.IOHandler) then begin
Danke |
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; |
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:
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 |
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. |
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; |
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. |
AW: Thread stürzt ab Indy TCPIP Client
Und wo hast du
Delphi-Quellcode:
und
TFoo
Delphi-Quellcode:
gefunden?
TClient
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:
den Client einfach aus dem Speicher zu entfernen.
EIdException
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. |
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 ;) |
AW: Thread stürzt ab Indy TCPIP Client
Bei einer Zugriffsverletzung hast du einen Programm-Fehler. Wie soll man darauf reagieren? Wenn man darauf reagieren kann, dann braucht man nicht mehr reagieren, denn man hat den ja beseitigt ;)
|
AW: Thread stürzt ab Indy TCPIP Client
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz