AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Dauerhafte TCP-Verbindung: Access Violation???
Thema durchsuchen
Ansicht
Themen-Optionen

Dauerhafte TCP-Verbindung: Access Violation???

Ein Thema von romber · begonnen am 23. Mär 2009 · letzter Beitrag vom 26. Mär 2009
Antwort Antwort
romber

Registriert seit: 15. Apr 2004
Ort: Köln
1.166 Beiträge
 
Delphi 10 Seattle Professional
 
#1

Dauerhafte TCP-Verbindung: Access Violation???

  Alt 23. Mär 2009, 16:05
Hallo!

Ich habe mir einen kleinen TCP-Klienten erstellt, der die Verbindung mit dem Server aufbaut und dauerhaft verbunden bleibt. Dazu habe ich noch einen Thread erstellt, der die Verbindung überwacht und bei Bedarf wieder aufbaut. Zudem wird sichergestellt, dass immer nur einen Client-Thread existiert. Manche werden Fragen, wofür das ganze gut ist und behaupten, es ist nicht gut so usw. Das weiß ich auch selbst und bin auch einverstanden, dass es nicht die korrekteste Lösung ist! Aber die Sache wurde damals für einen ganz bestimmten Einsatz programmiert, hat jahrelang gut funktioniert und funktioniert jetzt auch noch, jedenfalls macht es seine Aufgabe.

Zum eigentlichen Problem ist es erst jetzt gekommen. Ein Update muss her, der Code wird neu kompiliert, und zwar mit Delphi 2009 und Indy10. Schnell wurde der Code für Indy10 angepasst. Es funktioniert sogar, aber nicht mehr ohne Probleme. Der Überwachungsthread meldet nach mehreren Versuchen, die abgebrochene Verbindung wieder aufzubauen, eine AV und bricht ab. Auch beim Schließen des Programms erscheint häufig eine Access Violation. Um sicher zu gehen, habe ich die andere Code entfernt und nur diese meine zwei Threads gelassen, somit ist es sicher, dass der Fehler von den Threads verursacht wird. Ich habe schon vieles versucht - ohne Erfolg. Brauche Eure Hilfe!!!

Weiter unten habe ich den Code des Formulars und der Threads gepostet:


Bitte bitte, sagt mir, wo das Problem liegt.

Delphi-Quellcode:
 //Formular, wo das Ganze aktiviert oder deaktiviert wird
unit FormMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmMain = class(TForm)
    cbTCPConnection: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure cbTCPConnectionClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  frmMain: TfrmMain;
  ConnectionActive: Boolean;

implementation

uses
  Connection;

{$R *.dfm}

procedure TfrmMain.cbTCPConnectionClick(Sender: TObject);
begin
  ConnectionActive := cbTCPConnection.Checked;
  if cbTCPConnection.Checked = false then
  begin
    cbTCPConnection.Caption := 'nicht verbunden';
    if Assigned(TCPConnection) then
    TCPConnection.TCPClient.Disconnect;
  end
  else
  cbTCPConnection.Caption := 'Verbindung wird hergestellt...';
end;

procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Assigned(TCPConnection) then
  TCPConnection.TCPClient.Disconnect;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  ConnectionActive := cbTCPConnection.Checked;
  TConnectionWatcher.Create(false);
end;

initialization
  TCPConnection := nil;

end.

//Und hier die beiden Threads

unit Connection;

interface

uses
  Classes, Dialogs, SysUtils, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient;

type
   TTCPConnectionClient = class(TThread)
   constructor Create (CreateSuspended: Boolean);
   destructor Destroy; override;
 private
   Status: string;
   RestData: string;
 protected
   procedure Execute; override;
   procedure ClientStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String);
   procedure ChangeStatus;
 public
   TCPClient: TIdTCPClient;
   class function Use: TTCPConnectionClient;
end;

type
  TConnectionWatcher = class(TThread)
  constructor Create(CreateSuspended: Boolean);
  protected
    procedure Execute; override;
end;

var
  TCPConnection: TTCPConnectionClient;
  ConnectionCheckCounter: integer;

implementation

uses
  FormMain;

constructor TTCPConnectionClient.Create(CreateSuspended: Boolean);
begin
  inherited Create(CreateSuspended);
  FreeOnTerminate := true;
end;

destructor TTCPConnectionClient.Destroy;
begin
  if Assigned(TCPConnection) then
  TCPConnection := nil;
  inherited Destroy;
end;

procedure TTCPConnectionClient.ClientStatus(ASender: TObject; const AStatus: TIdStatus; const AStatusText: String);
begin
   if AStatus = hsConnecting then
   Status := 'Verbindung wird hergestellt...'
   else if AStatus = hsConnected then
   Status := 'verbunden'
   else if (AStatus = hsDisconnecting) or (AStatus = hsDisconnected) then
   Status := 'nicht verbunden';
   Synchronize(ChangeStatus);
end;

procedure TTCPConnectionClient.ChangeStatus;
begin
  frmMain.cbTCPConnection.Caption := Status;
end;

procedure TTCPConnectionClient.Execute;
var
  RowData, Data, ServerData: string;
begin
  ConnectionCheckCounter := 0;
  TCPClient := TIdTCPClient.Create(nil);
  TCPClient.OnStatus := ClientStatus;
  TCPClient.Host := 'localhost';
  TCPClient.Port := 44491;

  try
    TCPClient.Connect;
    while not Terminated and TCPClient.Connected do
    begin
      ConnectionCheckCounter := 0;
      ServerData := TCPClient.IOHandler.ReadLn();
      if Length(ServerData) > 0 then
      begin
        //Hier kommt der Code für die Bearbeitung der empfangenen Daten. Dieser Code ist in Ordnung und ist nicht die Ursache des Problems.
      end;
    end;
  except
  end;

  if TCPClient.Connected then
  TCPClient.Disconnect;
  TCPClient.Free;
end;

class function TTCPConnectionClient.Use: TTCPConnectionClient;
begin
  if not Assigned(TCPConnection) then
  begin
    TCPConnection := TTCPConnectionClient.Create(false);
  end;
  Result := TCPConnection;
end;


constructor TConnectionWatcher.Create;
begin
  inherited Create(CreateSuspended);
  FreeOnTerminate := true;
end;

procedure TConnectionWatcher.Execute;
begin
  while not Terminated do
  begin
    if ConnectionActive then
    begin
      if TCPConnection = nil then
      TCPConnection := TTCPConnectionClient.Use
      else
      begin
        ConnectionCheckCounter := ConnectionCheckCounter + 1;
        if ConnectionCheckCounter = 5 then
        begin
          if TCPConnection <> nil then
          TCPConnection.TCPClient.Disconnect;
        end;
    end;
    end;
    Sleep(1000);
  end;
end;

end.
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#2

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 23. Mär 2009, 20:28
Hi romber,

Zitat von romber:
Der Überwachungsthread meldet nach mehreren Versuchen, die abgebrochene Verbindung wieder aufzubauen, eine AV und bricht ab. Auch beim Schließen des Programms erscheint häufig eine Access Violation.
Zitat von romber:
Delphi-Quellcode:
procedure TConnectionWatcher.Execute;
begin
  while not Terminated do
  begin
    if frmMain.cbTCPConnection.Checked then // das dürfte Probleme verursachen
    begin
      ...
    end;
  end;
end;
Ad hoc fällt mir nur der unsychronisierte Zugriff auf das VCL Element (s.o.) auf - das ist immer wieder gerne ein Grund für AVs.

Kannst Du den Fehler nicht weiter eingrenzen? Springt der Debugger denn nicht rein?

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
romber

Registriert seit: 15. Apr 2004
Ort: Köln
1.166 Beiträge
 
Delphi 10 Seattle Professional
 
#3

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 23. Mär 2009, 21:33
Hi Assertor!

Danke für die Antwort!
Tatsächlich konnte das Problem bei unsinchronisiertem Zugriff liegen. Komisch ist, dass es damals mit Indy9 und Delphi7 dieses Problem nicht da war.
Ich versuche, den Fehler weiter einzugrenzen und melde mich wieder. Danke!
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#4

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 23. Mär 2009, 22:00
Hi,

Zitat von romber:
Danke für die Antwort!
Keine Ursache

Zitat von romber:
Tatsächlich konnte das Problem bei unsinchronisiertem Zugriff liegen. Komisch ist, dass es damals mit Indy9 und Delphi7 dieses Problem nicht da war.
Ich versuche, den Fehler weiter einzugrenzen und melde mich wieder. Danke!
Ja, vielleicht ist es wirklich nur eine kleine Ursache mit großer Wirkung. Das es bisher keine Probleme gab würde ich eher unter "Glück" einordnen - eine Mögliche Ursache ist es ja auf jeden Fall. Sag einfach bescheid hier.

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
romber

Registriert seit: 15. Apr 2004
Ort: Köln
1.166 Beiträge
 
Delphi 10 Seattle Professional
 
#5

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 24. Mär 2009, 10:52
Ich habe eine globale Variable "ConnectionActive" erstellt und prüfe diese, anstatt direkt auf das CheckBox zuzugreifen.
Fas Problem besteht leider nach wie vor.
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#6

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 24. Mär 2009, 11:43
Hi romber,

kannst Du bitte ein Demoprojekt machen (also Units und Forms) und als Zip hier im Thread posten?

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
romber

Registriert seit: 15. Apr 2004
Ort: Köln
1.166 Beiträge
 
Delphi 10 Seattle Professional
 
#7

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 24. Mär 2009, 12:30
Ich habe das Demo-Projekt angehängt. Die Routine zum Bearbeiten der empfangenen Daten sieht in meinem Projekt etwas anders aus als im Demo Projekt, der Server und Client kommunizieren nach einem bestimmten Protokol, aber an dieser Routine liegt der Fehler nicht. Ich muss auch noch sagen, das AV nicht immer auftaucht. Man sollte sich nicht wundern, wenn man das Projekt ausführt und alles glatt läuft. Es taucht plötzlich auf, manchmal nach mehreren Versuchen.

Das Problem taucht auf
- beim Schließen des Programms und
- beim Versuch des Überwachungsthreads, die abgebrochene Verbindung wieder herzustellen. Dabei wird der Überwachungsthread, der eigentlich immer laufen muss, beendet.
Angehängte Dateien
Dateityp: zip connection_779.zip (308,9 KB, 6x aufgerufen)
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#8

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 26. Mär 2009, 09:30
Hi romber,

ich habe Deine Demoprojekt bisher etliche Male durchlaufen lassen - aber bei keiner Konstellation have ich eine AV bekommen... Ich würde jetzt vorschlagen, daß Du die kostenfreie Version von madExcept mal in Deinem Projekt verwendest, damit Du wenn der Fehler auftritt einen genauen Bugreport bekommst. Das ist für die Suche viel einfacher. Diesen Bug Report kannst Du mir dann gerne mailen bzw. hier posten.

Leider kann ich da wohl im Moment nicht besser helfen...

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
romber

Registriert seit: 15. Apr 2004
Ort: Köln
1.166 Beiträge
 
Delphi 10 Seattle Professional
 
#9

Re: Dauerhafte TCP-Verbindung: Access Violation???

  Alt 26. Mär 2009, 15:58
Danke, Assertor!

Ich versuche es mit madExcept und melde mich wieder!
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:25 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