Entwickler-Ecke
Internet / Netzwerk - TIdTCPClient und Multithreading
holgerbremen - Mi 10.11.10 09:13
Titel: TIdTCPClient und Multithreading
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 - Mi 10.11.10 10:16
Bei solchen Problemen ist es immer hilfreich, wenn du mal deinen Code zeigst
holgerbremen - Mi 10.11.10 13:49
Init, IpConnect und Destroy. Das ist fast alles. Der Fehler tritt aber auch ohne den TClientThread auf.
Delphi-Quelltext
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 - 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 - 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 - 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 - 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 - 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 - 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.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!