Libnodave Anwendung schliessen

Zuviel Werbung?
-> Hier kostenlos registrieren
Nach meiner bisherigen Erfahrung passiert das tatsächlich nie mit kleinen Testanwendungen. Erst wenn es dann größer und verwickelter wird (Clientfenster, viele Komponenten etc.) passiert das dann irgendwann.
Mit der Größe der Anwendung hat das IMHO wenig zu tun (meine Systemdienste sind auch recht komplex), aber mit Sicherheit steigt mit der Anzahl der eingesetzten (Fremd-) Bibliotheken und Komponenten die Wahrscheinlichkeit des Auftretens von Fehlern. Nach meinen Erfahrungen übrigens bei gekauften Bibliotheken genau so häufig wie bei Freien (auch wenn QM oft einen anderen Standpunkt vertritt). Bei Fehlern, für die man auch noch bezahlt hat, tut man sich allerdings wesentlich leichter, dem Verantwortlichen die Pest an den Hals zu wünschen ... :ROFLMAO:


Gruß Axel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Snopy123123!
In VB beende ich die Verbindung wie folgt:

Private Sub Trennen()
' Verbindung abbauen
Dim RetCode As Long
If hConnection <> 0 Then
RetCode = daveDisconnectPLC(hConnection)
daveFree hConnection
hConnection = 0
End If
If hInterface <> 0 Then
RetCode = daveDisconnectAdapter(hInterface)
daveFree hInterface
hInterface = 0
End If
If hSocket <> 0 Then
RetCode = closePort(hSocket)
hSocket = 0
End If
End Sub

Das hat von Anfang an auf Anhieb funktioniert. Habe noch nie eine
Beschwerde von Windows (98,WIN2000,XP und Vista) gesehen.
m.f.G. alfonsmoeller
 
Zeig doch mal etwas Quellcode, wenn dein Projekt nicht zu geheim ist. Ich verwende TNoDave relativ oft und hatte noch nie Probleme damit im OnClose der Anwendung die Verbindung zu trennen.

Evtl. ist dein Problem, dass der Thread noch läuft, du die Verbindung aber schon getrennt hast.

Versuch's mal mit WaitFor beim Beenden des Threads.
 
Zeig doch mal etwas Quellcode, wenn dein Projekt nicht zu geheim ist. Ich verwende TNoDave relativ oft und hatte noch nie Probleme damit im OnClose der Anwendung die Verbindung zu trennen.

Evtl. ist dein Problem, dass der Thread noch läuft, du die Verbindung aber schon getrennt hast.

Versuch's mal mit WaitFor beim Beenden des Threads.

In der TNoDave wird der Thread beim schließen der Verbindung der Thread geschlossen und die Verbindung wird beim freigeben geschlossen... :TOOL:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zeig doch mal etwas Quellcode, wenn dein Projekt nicht zu geheim ist. Ich verwende TNoDave relativ oft und hatte noch nie Probleme damit im OnClose der Anwendung die Verbindung zu trennen.

Evtl. ist dein Problem, dass der Thread noch läuft, du die Verbindung aber schon getrennt hast.

Versuch's mal mit WaitFor beim Beenden des Threads.



Von geheim hat da niemand was gesagt ! Hier mal ein paar Schnipsel, Die Fehlermeldung beim Schliessen bekomme ich übrigens immer noch.



procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
vtest.Terminate;
vtest.WaitFor;
vtest.free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
vTest := tTest.Create(false);
end;


procedure TTest.execute;
var
MyNoDave : TNoDave;
begin

MyNoDave := TNoDave.Create(nil);
MyNoDave.IPAddress:= 'XXX.X.XX.XX';
MyNoDave.BufLen:= 100;
MyNoDave.CPUSlot:= 2;
MyNoDave.IntfName:= 'IF1';
MyNoDave.IntfTimeout:= 1500000;
MyNoDave.Protocol:= daveProtoISOTCP;
MyNoDave.Active:= True;

while not Terminated do begin
beendet := true;
i:=i+1;
Zaehl:= Zaehl+1;
Form1.Edit2.Text:= intToStr(Zaehl);

update(MyNoDave);
//self.free;
end; //while


mynodave.Active:= false;
MyNoDave.Free;

end;
 
Ein Versuch, mehr nicht ..

Hallo,

@snoopy123123

versuche mal folgendes :

Code:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  [COLOR="Red"]vtest.FreeOnTerminate := FALSE;[/COLOR]
  vtest.Terminate;
  vtest.WaitFor;
  vtest.free;
end;

Delphi hat da manchmal noch einige kleine Probleme mit dem Beenden von Threads, da läuft manchmal nicht alles so rund wie gewünscht.

Gruß

Question_mark
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Delphi und Threads

Hallo,

und hier noch ein kleines Tut von 'Luckie' aus einem Delphi-Forum. Ich denke mal, da wird einiges etwas klarer und verständlicher. Was Luckie in seinem Tut leider nicht berücksichtigt hat, sind diese kleinen Fehler in Delphi, u.a. beim WaitFor :eek:

http://www.delphi-library.de/topic_ThreadProgrammierung+unter+Windows+mit+Delphi_16627.html&sid=67ecc9a2da1cae3ba5771939cc05e609

Gruß

Question_mark
 
Was ich darin zu beanstanden hätte wäre diese Zeile:

Form1.Edit2.Text:= intToStr(Zaehl);

Das sollte man eigentlich in ein Synchronize packen, kann ganz schön schiefgehen!!!

Code:
procedure TTest.UpdateEdit;
begin
  Form1.Edit2.Text:= intToStr(Zaehl);
end;
 
procedure TTest.execute;
begin
  ...
  ...
  Synchronize(UpdateEdit);
  ...
  ...
end;
 
Was ich darin zu beanstanden hätte wäre diese Zeile:

Form1.Edit2.Text:= intToStr(Zaehl);

Recht hast du, das geht garantiert schief (eigene Erfahrung), auch wenn man es nicht sofort sieht oder merkt. Synchronize ist ein absolutes Muß, wenn man auf die Oberfläche und damit ebend andere VCL-Komponenten zugreift. Eigentlich wäre das Alles so nicht unbedingt nötig, die Komponente startet intern ihren eigenen Thread, um Daten zu holen und liefert die dann mit dem OnRead-Ereignis.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Versuch doch mal MyNoDave im FormCreate zu erzeugen, im Thread kannst du dann auch ohne synchronize() auf MyNoDave zugreifen, ohne das es kracht.

Den Thread würde ich auch nicht hier:

Code:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  vtest.Terminate;
  vtest.WaitFor;
  vtest.free;
end;
sondern hier:

Code:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  vtest.Terminate;
  vtest.WaitFor;
  vtest.free;
end;
oder hier:

Code:
procedure TForm1.FormDestroy(Sender: TObject);
begin
  vtest.Terminate;
  vtest.WaitFor;
  vtest.free;
end;

beenden.

Im CloseQuery kannst du z.B. eine Abfrage reinsetzen, ob die Anwendung wirklich geschlossen werden soll und dementsprechend CanClose true oder false setzen. Aber Objekte würde ich darin nicht freigeben.

Lade dir mal den FastMM4 runter und binde ihn ein, der Memorymanager zeigt dir beim Beenden an, wo es knallt. klick!
 
Zuletzt bearbeitet:
Wie sieht denn eigentlich die Deklaration von TTest aus?

Wenn du das aus dem Delphi-Forum übernommen hast sieht es wahrscheinlich so aus:

Code:
TTest = class(TThread)
   private

   protected
   //procedure update;

   public
   procedure execute; override;
   procedure update(MyNoDaveUpdate : TNoDave);
   end;

Richtig sollte aber sein:

Code:
TTest = class(TThread)

   private

   protected
     procedure execute; override;
     procedure update(MyNoDaveUpdate : TNoDave);
   end;
 
Zuletzt bearbeitet:
Das mit dem threadsafe kann afk bestimmt beantworten.
Yep, das kann ich. Ich nutze in meinen eigenen Programmen recht umfangreich Threads, und darum ist TNodave weitgehend auch threadsafe. Allerdings können logischerweise trotzdem Probleme auftreten (wie bei jeder anderen Komponente auch), wenn aus verschiedenen Threads überschneidend Properties verändert oder Methoden aufgerufen werden, die wiederum Properties verändern oder den internen Buffer nutzen. Und da die libnodave.dll aus prinzipiellen Gründen (liegt am S7-Protokoll) mit überschneidenden Funktionsaufrufen aus verschiedenen Threads heraus Probleme hat, habe ich das mit einer Critical Section innerhalb der Komponente abgesichert, was aber wiederum bei ungünstiger Programmierung vom Anwendungsprogramm zu einem Deadlock führen kann.

TNodave.Create und .Free innerhalb vom TThread.Execute sind kein Problem, allerdings stellt der Aufruf von Update(MyNodave) meine Kristallkugel mangels Quellcode vor ein kleineres Problem. Das größte Problem ist aber nach wie vor, daß eigentlich immer noch nicht klar ist, WO (im Programmcode) die Exception eigentlich ausgelöst wird. Die Debug-Units und/oder der Aufruf-Stack könnten hier durchaus etwas mehr Klarheit bringen, alles andere hier ist und bleibt wilde Spekulation ...


Gruß Axel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo allerseits,

bin mittlerweile nochmal ein stückchen weitergekommen. Die Speicherlecks treten nur auf wenn ich mehrere Forms in der Anwendung habe.

Wenn ich nur meine Haupform benutze und die Komponente mit formcreate erstelle und dann über nen thread die Daten lese funktioniert und die Anwendung lässt sich auch sauber schliessen.
Füge ich nun eine zweite form ein, und dabei meine ich nur die blanke form dann tritt der speicherfehler beim schliessen auf. Kommentiere ich nun das
Application.createform im Projectquelltext aus dann schliesst die Anwendung wieder sauber. Habt ihr ne erklärung hierfür ?

Code:
program Project1;

uses
FastMM4,
Forms,
Unit1 in 'Unit1.pas' {Form1},

Unit3 in 'Unit3.pas' {Setup};

{$R *.res}

begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
//Application.CreateForm(TSetup, Setup);
Application.Run;
end.
 
Ich weiss auch nicht mehr weiter ...

Hallo,

snoopy schrieb:
Habt ihr ne erklärung hierfür ?

Ganz ehrlich gesagt, aus dem bisher geschriebenen kann ich keine Erklärung finden. Schick mir das Projekt doch mal über den Teich (mit evtl. Fremdkomponenten), dann kann ich am Wochenende mal nachschauen.

Gruß

Question_mark
 
Habt ihr ne erklärung hierfür ?
Verdammt, wo ist denn blos wieder meine Kristallkugel ... :rolleyes:

Mal im Ernst ...
  • FastMM liefert Logdateien mit Hinweisen darauf, WANN es im Programm kracht,
  • im Debugger von der Delphi-IDE kann man bei einer Exception im Aufruf-Stack sehen, WO es im Programm kracht,
  • wenn man ein Programm mit den Debug-DCUs erstellt, dann kann man das sogar dann noch schrittweise im Debugger laufen lassen, wenn das Programm in den Code der VCL abtaucht, um herauszufinden, WARUM es im Programm kracht,
...und wir sollen jetzt aufgrund des Hinweises auf eine auskommentierte Zeile im Projekt-Quelltext (also der allerobersten Ebene des Programms) sagen, woran das liegen kann ?

Oh, da ist ja meine Kristallkugel ... mal schauen ... ah, klar: 42 ! :cool:


Gruß Axel
 
Zurück
Oben