Autor |
Beitrag |
holgerbremen
      
Beiträge: 120
|
Verfasst: Mi 10.11.10 09:13
Ich habe ein Problem mit dem TIdTCPClient, wo ich nicht so richtig weiterkomme.
Ich habe eine Anwendung mit 8 Threads. Jeder Threads macht eine Verbindung per TIdTCPClient zum einem Server. Die Threads verbinden sich, senden Daten und beenden sich wieder. Solange alle Threads sich Connecten können, läuft alles. Sobald aber ein Thread auf ein Timeout läuft (500ms), bekomme ich Exceptions, obwohl ich den Connect per Try/Catch überwache (Fehler 10038 Socket Operation on non-Socket). Auch eine ConnectionTimeout-Exception kommt aus den Tiefen der Indys, trotz Try/Catch.
Lasse ich nur einen Thread laufen, klappt alles ohne Probleme. Ist der TIdTCPClient überhaupt Threadsicher. Irgendwie geht meine Vermutung dahin, dass dort die Ursache ist.
|
|
matze
      
Beiträge: 4613
Erhaltene Danke: 24
XP home, prof
Delphi 2009 Prof,
|
Verfasst: Mi 10.11.10 10:16
Bei solchen Problemen ist es immer hilfreich, wenn du mal deinen Code zeigst
_________________ In the beginning was the word.
And the word was content-type: text/plain.
|
|
holgerbremen 
      
Beiträge: 120
|
Verfasst: Mi 10.11.10 13:49
Init, IpConnect und Destroy. Das ist fast alles. Der Fehler tritt aber auch ohne den TClientThread auf.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86:
| procedure TTCPBase.Init(sIP : string; nPort : integer); begin try m_Thread := nil; m_bConnected := false; m_TCPClient := TIdTCPClient.Create(self); m_TCPClient.OnStatus := TCPOnClientStatus; m_TCPClient.Port := nPort; m_TCPClient.Host := sIP; except on E : Exception do begin Protokoll(format('Controller_ID [%d] -> Fehler bei TTCPBase.Init(). [%s]', [CTR_ID, e.Message]), LogLevel.lvError); end end; end;
function TTCPBase.IPConnect(const ATimeout: Integer = IdTimeoutDefault) : Boolean; var s : string; begin
try
if (not m_bConnected )then begin m_TCPClient.ConnectTimeout := 300; m_TCPClient.Connect();
m_Thread := TClientThread.Create(True); m_Thread.Resume;
m_bConnected := true; result := true; end else begin result := true; end;
except on E : Exception do begin
m_bConnected := false; result := false; s := e.Message; Protokoll(format('Controller_ID [%d] -> Fehler beiTTCPBase.IPConnect(). [%s]', [CTR_ID, s]), LogLevel.lvError); end; end; end;
destructor TTCPBase.Destroy(); begin
try
if m_TCPClient <> nil then begin if (m_TCPClient.Connected) then m_TCPClient.Disconnect;
m_TCPClient.Destroy(); m_TCPClient := nil; end;
if (m_Thread <> nil) then begin m_Thread.Terminate; Sleep(10); while (m_Thread.Terminated = false) do Sleep(10); end;
except on E : Exception do begin Protokoll(format('Controller_ID [%d] -> Fehler bei TTCPBase.Destroy(). [%s]', [CTR_ID, e.Message]), LogLevel.lvError); end end;
inherited;
end; |
Moderiert von Gausi: Code- durch Delphi-Tags ersetzt
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 10.11.10 13:57
Nach dem Terminate benutze einfach WaitFor statt der komischen Schleife...
Die bringt nämlich rein gar nix. Terminated wird durch Terminate auf True gesetzt und ob der Thread schon abgebrochen ist oder nicht, bekommst du gar nicht mit.
|
|
holgerbremen 
      
Beiträge: 120
|
Verfasst: Mi 10.11.10 15:00
Soweit so gut. Anscheindend stimmt noch was anderes nicht.
So bekomme ich folgede Exception "Ein extern ersteller Thread kann nicht beendet werden.". Was soll mir das nun sagen?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if (m_Thread <> nil) then begin m_Thread.Terminate; m_Thread.WaitFor;
end; |
Moderiert von matze: Code- durch Delphi-Tags ersetzt
|
|
holgerbremen 
      
Beiträge: 120
|
Verfasst: Mi 10.11.10 15:46
holgerbremen hat folgendes geschrieben : | Soweit so gut. Anscheindend stimmt noch was anderes nicht.
Bei WaitFor erscheint die Exception "Das Handle ist ungültig (6)"
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if (m_Thread <> nil) then begin m_Thread.Terminate; m_Thread.WaitFor;
end; | |
Moderiert von matze: Code- durch Delphi-Tags ersetzt
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 10.11.10 17:40
Vielleicht hast du aus Versehen FreeOnTerminate angeschaltet und der Thread hat sich schon selber "fertig gemacht", wenn du auf ihn warten möchtest.
|
|
holgerbremen 
      
Beiträge: 120
|
Verfasst: Mi 10.11.10 22:03
Zitat: | Vielleicht hast du aus Versehen FreeOnTerminate angeschaltet und der Thread hat sich schon selber "fertig gemacht", wenn du auf ihn warten möchtest. |
Das war es, danke. Hätte ich auch selber sehen können.
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 10.11.10 22:19
Das sieht aber so aus als hättest du da noch weitere logische Fehler:
Erstens erzeugst du außerhalb des Threads eine TCP Client Komponente. Warum? Die solltest du am sinnvollsten im Thread erzeugen, sonst kommst du nur mit der Synchronisation der Ereignisse usw. durcheinander.
Zweitens zerstörst du zuerst den Client und dann erst den Thread. Das heißt der Thread greift ggf. auf eine bereits zerstörte Komponente zu, weil der dann noch läuft.
|
|