Autor Beitrag
holgerbremen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 120



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 4613
Erhaltene Danke: 24

XP home, prof
Delphi 2009 Prof,
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 120



BeitragVerfasst: Mi 10.11.10 13:49 
Init, IpConnect und Destroy. Das ist fast alles. Der Fehler tritt aber auch ohne den TClientThread auf.

ausblenden volle Höhe 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
          // TidTCPClient
          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 <> nilthen
  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 user profile iconGausi: Code- durch Delphi-Tags ersetzt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 120



BeitragVerfasst: 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?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  if (m_Thread <> nilthen
  begin
    m_Thread.Terminate;
    m_Thread.WaitFor;

//    Sleep(20);
//    while (m_Thread.Terminated = false) do
//        Sleep(10);
  end;


Moderiert von user profile iconmatze: Code- durch Delphi-Tags ersetzt
holgerbremen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 120



BeitragVerfasst: Mi 10.11.10 15:46 
user profile iconholgerbremen hat folgendes geschrieben Zum zitierten Posting springen:
Soweit so gut. Anscheindend stimmt noch was anderes nicht.
Bei WaitFor erscheint die Exception "Das Handle ist ungültig (6)"

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  if (m_Thread <> nilthen
  begin
    m_Thread.Terminate;
    m_Thread.WaitFor;

//    Sleep(20);
//    while (m_Thread.Terminated = false) do
//        Sleep(10);
  end;


Moderiert von user profile iconmatze: Code- durch Delphi-Tags ersetzt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 120



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.