Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Pinger Tool (https://www.delphipraxis.net/176209-pinger-tool.html)

Balthasar 19. Aug 2013 18:09

Pinger Tool
 
Hallöchen! Ich versuche in Delphi ein Chat-Programm zu realisieren und arbeite mit den alten ClientSocket und ServerSocket Komponenten. Im Moment hänge ich bei folgendem Problem:
Meine Klasse TPinger leitet sich von TThread ab, ich versuche zu jeder vollen Sekunde alle am Chat beteiligten Personen zu pingen. Die PING() Methode im Code unten macht lediglich folgendes:
Delphi-Quellcode:
Socket.SendText('PING!');
Delphi-Quellcode:
procedure TPinger.Execute;
begin
    while not Terminated or (benutzer <> nil) or (benutzer.getSocket <> nil) do
    begin
      benutzer.PING();
      Sleep(1000);
    end;
end;
So weit so gut. Das Programm startet und läuft auch ohne Probleme, die Pings kommen zügig an und alles scheint bestens. Beim Disconnecten des Clients jedoch, crasht das Programm vollständig. Fehlermeldung gibt es keine direkt. Läuft die Anwendung außerhalb der Entwicklungsumgebung, so crasht sie einfach ("Projekt1.exe funktioniert nicht mehr und muss beendet werden."). Lasse ich das Projekt innerhalb der Entwicklungsumgebung zum Fehler kommen, poppt der Debugger auf und zeigt mir irgendeinen Assembler-Code oder so.

Mein Verdacht liegt darin, dass der Thread trotz Anweisung bei fehlendem "Benutzerobjekt" oder dem fehlenden Socket des Benutzerobjekts abzubrechen einfach nicht abbricht sondern ins leere tritt und stirbt. Jemand ne idee wie ich das Problem lösen könnte?

Mfg
Balthasar

Union 19. Aug 2013 18:14

AW: Pinger Tool
 
Wie wäre es mit and?

Balthasar 19. Aug 2013 18:17

AW: Pinger Tool
 
Zitat:

Zitat von Union (Beitrag 1225372)
Wie wäre es mit and?

Der soll ja sofort aufhören wenn eines dieser Kriterien nicht mehr erfüllt wird. Mit AND würde er nur dann aufhören wenn alle 3 Fälle (oder je nach dem welche Fälle man bindet) eintreten.

Helmi 19. Aug 2013 19:02

AW: Pinger Tool
 
and ist schon richtig

wenn man es etwas umschreibt (nur zum Verständnis) dann wird's eindeutiger warum:

Delphi-Quellcode:
while (not Terminated) and (not benutzer = nil) and (not benutzer.getSocket = nil) do
Zitat:

solange (nicht Terminated) und (nicht benutzer = nil) und (nicht benutzer.getSocket = Nil)
Schleifeninhalt abarbeiten
Eine While-Schleife arbeitet solange, solange das Argument true ist

Union 19. Aug 2013 19:04

AW: Pinger Tool
 
Zitat:

Zitat von Balthasar (Beitrag 1225373)
Zitat:

Zitat von Union (Beitrag 1225372)
Wie wäre es mit and?

Der soll ja sofort aufhören wenn eines dieser Kriterien nicht mehr erfüllt wird. Mit AND würde er nur dann aufhören wenn alle 3 Fälle (oder je nach dem welche Fälle man bindet) eintreten.

So wie es dort steht heißt es aber, daß er solange weitermacht, wie eine der drei Bedingungen noch zutrifft.

Balthasar 19. Aug 2013 20:06

AW: Pinger Tool
 
Komisch, vllt lebe ich in einer invertierten Welt :D

Vielen Dank bislang, aber es geht immer noch nicht, gleicher Fehler :(

sx2008 19. Aug 2013 22:07

AW: Pinger Tool
 
Wenn dein Hauptformular geschlossen wird, solltest du den Thread(s) höflich mitteilen, dass jetzt Schluß ist:
Delphi-Quellcode:
mythread.Terminate; // setzt property Terminated auf True
Sleep(1050); // warten bis Thread sich selbst beendet hat
Grundsätzlich ist es gefährlich, wenn Threads weiterlaufen aber der Hauptthread terminiert wird.
Dazu musst du natürlich die Thread-Objekte in einer Variablen speichern, damit du beim Programmende darauf zugreifen kannst.
Der Sleep()-Aufruf ist zwar etwas primitiv, weil so die ganze Anwendung min. 1 Sekunde nicht reagiert aber als schnelle, einfache Lösung geht das schon.
Du kannst die Reaktionszeit bis die Threads auf das
Delphi-Quellcode:
Terminate
reagieren so verringern:
Delphi-Quellcode:
procedure TPinger.Execute;
var
  i : Integer;
begin
    i := 0;
    while not Terminated or (benutzer <> nil) or (benutzer.getSocket <> nil) do
    begin
      if i mod 5 = 0 then
         benutzer.PING(); // 1 Ping ungefähr alle 1000ms
      Inc(i);
      Sleep(200);
    end;
end;

Balthasar 19. Aug 2013 22:45

AW: Pinger Tool
 
Zitat:

Zitat von sx2008 (Beitrag 1225401)
Wenn dein Hauptformular geschlossen wird, solltest du den Thread(s) höflich mitteilen, dass jetzt Schluß ist:
Delphi-Quellcode:
mythread.Terminate; // setzt property Terminated auf True
Sleep(1050); // warten bis Thread sich selbst beendet hat
Grundsätzlich ist es gefährlich, wenn Threads weiterlaufen aber der Hauptthread terminiert wird.
Dazu musst du natürlich die Thread-Objekte in einer Variablen speichern, damit du beim Programmende darauf zugreifen kannst.
Der Sleep()-Aufruf ist zwar etwas primitiv, weil so die ganze Anwendung min. 1 Sekunde nicht reagiert aber als schnelle, einfache Lösung geht das schon.
Du kannst die Reaktionszeit bis die Threads auf das
Delphi-Quellcode:
Terminate
reagieren so verringern:
Delphi-Quellcode:
procedure TPinger.Execute;
var
  i : Integer;
begin
    i := 0;
    while not Terminated or (benutzer <> nil) or (benutzer.getSocket <> nil) do
    begin
      if i mod 5 = 0 then
         benutzer.PING(); // 1 Ping ungefähr alle 1000ms
      Inc(i);
      Sleep(200);
    end;
end;

Das ist ein wirklich sehr guter Vorschlag, ich danke vielmals.
Mittlerweile ist mein Problem auch komplett gelöst, im While-Block fehlte lediglich eine weitere Bedingung an die ich anfangs nicht dachte: (benutzer.getSocket.connected).
Mittlerweile kämpfe ich gegen andere Probleme, aber die schaffe ich schon wenn ich etwas mehr beider Sache bin :D
Danke nochmals an alle Helfer!!


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:11 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