[Delphi] TIdTCPClient uitlezen in een thread

Pagina: 1
Acties:
  • 288 views sinds 30-01-2008
  • Reageer

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Ik wil dat het uitlezen van een TIdTCPClient in een thread gebeurd. Daar had ik de volgende oplossing voor bedacht. Dit is alleen de Execute procedure van een eigen TThread object:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
procedure TTCPClientReader.Execute;
var
  Line: String;
begin
  while FTCPClient.Connected do
  begin
    try
      Line := FTCPClient.ReadLn;
      if Line <> '' then
      begin
        FData := Line;
        Synchronize(DoNewLineEvent);
      end;
    except
      FTCPClient.Disconnect;
    end;
  end;
end;

Dit werk aardig goed. Maar als de TCPClient verbroken wordt dat treedt er een exception op ("Not Connected") op de ReadLn regel.

Hoe kan dit aangezien ik toch steeds controleer of de verbinding nog bestaat. Doe ik iets heel erg verkeer in deze oplossing?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22-05 16:53
Delphi schreef op 05 oktober 2002 @ 16:09:Dit werk aardig goed. Maar als de TCPClient verbroken wordt dat treedt er een exception op ("Not Connected") op de ReadLn regel.

Hoe kan dit aangezien ik toch steeds controleer of de verbinding nog bestaat. Doe ik iets heel erg verkeer in deze oplossing?
Ik weet niet veel van Delphi, maar in de Winsock lib is het volgens mij zo dat je pas bij een read van je socket kunt zien dat de remote kant heeft gedisconnect. ( Zeker als de remote kant is gecrashed ) Je zult dus de returnvalue van je read moeten opvangen, of een eventuele exception.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
farlane schreef op 05 oktober 2002 @ 16:56:
[...]


Ik weet niet veel van Delphi, maar in de Winsock lib is het volgens mij zo dat je pas bij een read van je socket kunt zien dat de remote kant heeft gedisconnect. ( Zeker als de remote kant is gecrashed ) Je zult dus de returnvalue van je read moeten opvangen, of een eventuele exception.
Dat klopt idd. Maar de RealLn van Indy checkt op een disconnect. Ook als ik zelf check op een disconnect helpt dat niet.

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Oke, ben al een stukje verder:

Zodra er geen data meer is blijft deze regel hangen:
code:
1
        Line := FTCPClient.ReadLn;

Opzich geen probleem, aangezien dit alles in een thread zit. Zelfs heel goed!

Maar als ik dan vanuit een andere plaats in mijn programma de verbinding verbreek geeft ie dus een exception op die regel hierboven.

Ik vrees dat alleen een try-except block uitkomst biedt.

Overigens heb ik het geheel een beetje aangepast:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
procedure TTCPClientReader.Execute;
var
  Line: String;
begin
  while (not Terminated) and (FTCPClient.Connected) do
  begin
    CriticalSection.Enter;
    try
      try
        Line := FTCPClient.ReadLn;
        if Line <> '' then
        begin
          FData := Line;
          DoNewLineEvent;
        end;
      except
        //eventueel hier een FTCPClient.Disconnect
      end;
    finally
      CriticalSection.Leave;
    end;
  end;
end;


Edit:
uuhmm, ReadLn blijft idd wachten op data. Als de server waarmee de client is verboden z'n sockets sluit heeft de client (ik dus) een probleem.

Iemand al eens een TIdTCPClient in een thread uitgelezen, of gebruiken jullie alleen maar Timers daarvoor?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • ProgrammerX
  • Registratie: Juli 2002
  • Laatst online: 26-02-2021
Delphi schreef op 05 oktober 2002 @ 21:36:
Oke, ben al een stukje verder:

Zodra er geen data meer is blijft deze regel hangen:
code:
1
        Line := FTCPClient.ReadLn;

Opzich geen probleem, aangezien dit alles in een thread zit. Zelfs heel goed!

Maar als ik dan vanuit een andere plaats in mijn programma de verbinding verbreek geeft ie dus een exception op die regel hierboven.

Ik vrees dat alleen een try-except block uitkomst biedt.

Overigens heb ik het geheel een beetje aangepast:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
procedure TTCPClientReader.Execute;
var
  Line: String;
begin
  while (not Terminated) and (FTCPClient.Connected) do
  begin
    CriticalSection.Enter;
    try
      try
        Line := FTCPClient.ReadLn;
        if Line <> '' then
        begin
          FData := Line;
          DoNewLineEvent;
        end;
      except
        //eventueel hier een FTCPClient.Disconnect
      end;
    finally
      CriticalSection.Leave;
    end;
  end;
end;


Edit:
uuhmm, ReadLn blijft idd wachten op data. Als de server waarmee de client is verboden z'n sockets sluit heeft de client (ik dus) een probleem.

Iemand al eens een TIdTCPClient in een thread uitgelezen, of gebruiken jullie alleen maar Timers daarvoor?
Krijg je geen time-out van de server dan die je kan opvangen ?? Lijkt me sterk dat ie voor altijd blijft wachten :)

Een andere oplossing kan misschien zijn dat je in een andere thread (soort van watchdog) deze thread bewaakt en/of een aantal eigenschappen controleert (zoals de verbinding met de server). Als deze thread dan opmerkt dat de verbinding weg is, kun je de thread met de readln killen.

Verwijderd

Als je effe in de source kijkt, staat er:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
      (* ************************************************************* //
      ------ If you receive an exception here, please read. ----------

      If this is a SERVER
      -------------------
      The client has disconnected the socket normally and this exception is used to notify the
      server handling code. This exception is normal and will only happen from within the IDE, not
      while your program is running as an EXE. If you do not want to see this, add this exception
      or EIdSilentException to the IDE options as exceptions not to break on.

      From the IDE just hit F9 again and Indy will catch and handle the exception.

      Please see the FAQ and help file for possible further information.
      The FAQ is at http://www.nevrona.com/Indy/FAQ.html

      If this is a CLIENT
      -------------------
      The server side of this connection has disconnected normaly but your client has attempted
      to read or write to the connection. You should trap this error using a try..except.
      Please see the help file for possible further information.

      // ************************************************************* *)

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Topicstarter
Aha. Ik heb het allemaal opgelost. Beetje van de IdTelnet.pas afkijken:
tcpclient.pas

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Parcye
  • Registratie: Maart 2001
  • Laatst online: 24-08-2017

Parcye

Mr C

Giga Schop...

Ik heb dus op een gelijke manier een trhead gemaakt echter heb ik het idee dat als ik ReadLn doe hij zeg maar verdwijnt in de ReadLn en niet verder gaat tot er iets terug komt...

Nu heb ik ook ReadLn('', 200); gebruikt (wacht 200ms) maar ook daar heb ik het idee dat die verdwijnt, dus dat hij niet verder gaat met de lus TOTDAT er data binnen komt...

Iemand hier een oplossing voor?

"Als je het kan bedenken, kan het gemaakt worden" Parcye - 14 januari 2002

Pagina: 1