Libnodave Anwendung schliessen

Zuviel Werbung?
-> Hier kostenlos registrieren
So einfach ist das nicht ...

Hallo,

human schrieb:
aber wenn ich meinen Prozess beende dann gibt das Windows auch ohne, dass ich das freigebe wieder frei!

Ich höre jetzt zum ersten Mal, dass Windows so einen intelligenten "Garbage collector" eingebaut hat...
Google mal nach Eureka Log, dann lernst Du, wieviel Speicherlücken derartige Art der Programmierung erzeugen kann. Und vor allen Dingen hast Du dann ein Tool, mit dem man solche Speicherfresser aufspüren kann.
Oder erzeuge mal ganz einfach in einer Applikation eine große Anzahl von Objekten dynamisch zur Laufzeit und beende Deine Applikation, ohne diese Objekte wieder freizugeben. Nach einer endlichen Anzahl von Ausführen Deiner Applikation kotzt Dir Windows entgegen, dass nicht mehr genug Speicher zur Verfügung steht :ROFLMAO:
Wenn so eine Applikation in einer 24/7 Laufzeit und in der Industrie stabil laufen soll, muss man schon etwas mehr Aufwand treiben als ein paar Komponenten auf ein Formular zu ziehen...

Gruß

Question_mark
 
Noch einmal

Hallo,

human schrieb:
Das Destroy soll man normal nur nehmen, wenn es kein Free gibt

Verdammt nochmal, willst Du mich nicht verstehen ?

Wenn die Komponente statisch durch ziehen auf das Parent Formular gezogen und automatisch erzeugt wird, darfst Du niemals ein "Free" oder auch "Destroy" oder "FreeAndNil" auf diese Komponente anwenden, sonst knallt es meistens im Gebälk ...

Gruß

Question_mark
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Verdammt nochmal, willst Du mich nicht verstehen ?

Wenn die Komponente statisch durch ziehen auf das Parent Formular gezogen und automatisch erzeugt wird, darfst Du niemals ein "Free" oder auch "Destroy" oder "FreeAndNil" auf diese Komponente anwenden, sonst knallt es meistens im Gebälk ...
Nö, warum denn? Hin und wieder muss man doch mal sein Forumla aufräumen! (siehe Anhang (Formular mit TEdit und wird mit dem Button mit Free freigegeben, bei mir knallt da nix!!!))

Und er hat niergends geschrieben wie er sie erstellt, ich erstell die immer zur Laufzeit...

Ich höre jetzt zum ersten Mal, dass Windows so einen intelligenten "Garbage collector" eingebaut hat...
Bin ich mal davon ausgegangen, da Windows ja für jeden Prozess einen eigenen Speicherbereich anlegt, auf das "Normalerweise" (gibt ja proktische Funktionen, mit denen man doch auf andere Programme kommt) kein anderes Programm zugreifen kann, ich lass mich natürlich auch immer gern vom Gegenteil überzeugen!
 

Anhänge

  • Free.zip
    213,8 KB · Aufrufe: 7
Delphi hat auch einen Debugger ...

Hallo,

snoopy123123 schrieb:
versucht die komponente bei on close zu entfernen und selbst dann bekomm ich die Exception.

Natürlich, weil unter Umständen der Parent, also das Delphi Formular, die Komponente schon freigegeben hat. Das ist eher zufällig bedingt, da es davon abhängt, wann Delphi die Komponente freigibt. Das hängt schon davon ab, in welcher Reihenfolge die Formulare erzeugt werden. Ist also eher etwas "unpredictable".

Wenn Du die Komponente durch Ziehen auf das Formular erzeugt hast, dann unterlasse alle Versuche, diese irgendwann per Programmcode freizugeben.
Damit hast Du schon mal eine Fehlerquelle ausgeschlossen.
Dennoch besteht offensichtlich ein Problem beim Beenden des Programms und mit der Freigabe von TLibNoDave.
Das kann eigentlich nur zwei Ursachen haben :

1) Ein Fehler in der Komponente
2) Ein Fehler bei der Anwendung der Komponente durch den User

Ich halte den Punkt 2 für wahrscheinlicher, da es ja offensichtlich bei vielen anderen Anwendungen funktioniert.
Wird die Komponente eventuell aus einem TimerEvent oder einem Thread aufgerufen, der noch nicht beendet wurde, bevor der Parent der Komponente von Delphi freigegeben wurde. Dann ist auch die Komponente zerstört und dann gibt es die von Dir beschriebenen Exceptions.
Und dann setze mal einen Breakpoint in das OnClose Event des ParentForm der Komponente. Und schaue mal, ob dort der Zeiger auf LibNoDave beim Eintritt in den Event schon auf NIL gebogen ist ...

Gruß

Question_mark
 
Dann mach mal so weiter

Hallo,

human schrieb:
Nö, warum denn? Hin und wieder muss man doch mal sein Forumla aufräumen! (siehe Anhang (Formular mit TEdit und wird mit dem Button mit Free freigegeben, bei mir knallt da nix!!!))

Und er hat niergends geschrieben wie er sie erstellt, ich erstell die immer zur Laufzeit...

Snoopy hat schon geschrieben, dass die Komponente durch ziehen auf das Formular automatisch erzeugt wird ...

Ich respektiere natürlich Deinen Umgang mit der Erzeugung und Freigabe von Komponenten in Delphi, allein Deine Meinung teile ich nicht mit Dir.

Gruß

Question_mark
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie gesagt, gerade die Threads in Delphi sind oft etwas eigen. Mal kann man sie nicht abschießen, mal beendet man sie, aber sie verschwinden einfach nicht komplett, sondern vegetieren als "Leiche" vor sich hin. Das ist etwas mystisch und erfordert einiges an Testerei. (Delphi7)
 
Ich respektiere natürlich Deinen Umgang mit der Erzeugung und Freigabe von Komponenten in Delphi, allein Deine Meinung teile ich nicht mit Dir.

Naja, ich programmiere so eigentlich auch nie, aber dass es nicht geht oder mit deinen Worten dass es dann im Gebälk mächtig splittert stimmt ja auch nicht ganz!

Wie gesagt, gerade die Threads in Delphi sind oft etwas eigen. Mal kann man sie nicht abschießen, mal beendet man sie, aber sie verschwinden einfach nicht komplett, sondern vegetieren als "Leiche" vor sich hin. Das ist etwas mystisch und erfordert einiges an Testerei. (Delphi7)

Das ändert sich auch nicht mit den neueren Versionen...
 
Programme können auch Zufallsgeneratoren sein *gg*

Hallo,

Ralle schrieb:
Das ist etwas mystisch und erfordert einiges an Testerei.

Das ist in keiner Weise mystisch oder rätselhaft, sondern erfolgt nach streng (vom OS ) vorgegebenen Regeln. Und die VCL von Delphi ist eben nicht threadsafe, d.h. wenn Du aus einem erzeugten Thread die Delphi VCL ansprichst und die Spielregeln über "Synchronize" nicht beachtest, knallt es eben. Das ist aber kein Fehler in Delphi, sondern vom Programmierer, und das Problem dürfte wohl in den meisten Hochsprachen bestehen.

Gruß

Question_mark
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist in keiner Weise mystisch oder rätselhaft, sondern erfolgt nach streng (vom OS ) vorgegebenen Regeln. Und die VCL von Delphi ist eben nicht threadsafe, d.h. wenn Du aus einem erzeugten Thread die Delphi VCL ansprichst und die Spielregeln über "Synchronize" nicht beachtest, knallt es eben. Das ist aber kein Fehler in Delphi, sondern vom Programmierer, und das Problem dürfte wohl in den meisten Hochsprachen bestehen.

Damit hab ich eigentlich keine Probleme, alles was ein Thread wissen muss kriegt er direkt nach dem Erstellen von mir gesagt und wird dann erst gestartet oder eben wie erwähnt über Synchronize.

Das mysteriöse bei den Threads ist das Beenden (siehe http://www.sps-forum.de/showthread.php?t=29029 (der Teil mit Assigned(), den ich ausgeklammert habe), irgendwo schwirrt der noch rum, aber ist niemals vollkommen ganz weg. :confused:
FreeOnTerminate hilft nicht, Free auch nicht...
 
Das Suspend unterbricht nur die Ausführung der Threads temporär und wird nicht beendet:

Auszug aus der Delphihilfe:
Mit Suspend können Sie die Ausführung eines Thread temporär unterbrechen. Mit Resume kann die Ausführung anschließend wieder aufgenommen werden. Suspend-Aufrufe können verschachtelt sein. Entsprechend oft muss dann aber auch Resume aufgerufen werden, bevor der Thread fortgeführt wird.

Und Terminate macht ja auch nix was wirklich intern verwendet wird, sondern nur als "Programmierhilfe" bereitgestellt wird um Threads, die ständig im Hintergrund laufen, zu beenden, wenn die Eigenschaft "Terminated" auf TRUE steht:

procedure TThread.Terminate;
begin
FTerminated := True;
end;
 
Zuviel Werbung?
-> Hier kostenlos registrieren
...

human schrieb:
Das Suspend unterbricht nur die Ausführung der Threads temporär und wird nicht beendet:

Es ist eigentlich völlig überflüssig, dass Du mir die Funktion "Suspend" erklären willst ... Es kann nur verhindern, dass Deine App vor dem Terminate versucht noch auf VCL Elemente zuzugreifen, der Thread ist dann eben eingeschlafen ...

Gruß

Question_mark
 
Hallo,

Und Terminate macht ja auch nix was wirklich intern verwendet wird, sondern nur als "Programmierhilfe" bereitgestellt wird um Threads, die ständig im Hintergrund laufen, zu beenden, wenn die Eigenschaft "Terminated" auf TRUE steht:

Da hast Du allerdings übersehen, dass in den gängigen Hochsprachen jedes Property die Eigenschaft "read" und "write" hat und dementsprechend beeinflusst werden kann.

Gruß

Question_mark
 
Hallo,



Da hast Du allerdings übersehen, dass in den gängigen Hochsprachen jedes Property die Eigenschaft "read" und "write" hat und dementsprechend beeinflusst werden kann.

Gruß

Question_mark

property Terminated: Boolean read FTerminated;

Aber irgendwie kommt mir das vor, als wenn wir gerade über Äpfel (Thread greift auf VCL-Komponenten zu) und Birnen (Thread ist nach beenden immernoch (zumindest teilweise) da und lässt sich nicht komplett entfernen) sprechen... :confused:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Aber irgendwie kommt mir das vor, als wenn wir gerade über Äpfel (Thread greift auf VCL-Komponenten zu) und Birnen (Thread ist nach beenden immernoch (zumindest teilweise) da und lässt sich nicht komplett entfernen) sprechen... :confused:

Ja, ich kenne dieses eigenartige Verhalten auch. Es hat mich enorm viel Arbeit gekostet, das irgendwie hinzubasteln. Threads, die ich nochmal brauche halte ich an und benutze sie später wieder, völlig weg bekommt man die einfach nicht.

@qm
Ja qm, wir sind ja nun auch nicht total dämlich, Synchonize kenn ich grad noch. Leider macht das oft, den Geschwindigkeitsvorteil eines eigenen Thread wieder zunichte, weil auf irgendwelche Dinge vom BS gewartet wird.

Und klar folgt das OS strengen Regeln, sonst ginge gar nichts mehr und das sofort. Das Hauptprolem ist oft, daß man X verschiedene Komponenten, von X unterschiedlichen Herstellern, alle mit unterschiedlicher Qualität, nutzt. Da funkt schnell mal etwas dazwischen, ohne das man das so einfach rausbekommt. Wird bei der Exception, wie oben beschrieben, auch ein ähnliches Problem sein.
 
Als (Mit-)Verantwortlicher für diesen Thread muß ich mich wohl auch mal einmischen:

Ich glaube nicht, daß das Ausgangsproblem was mit Threads zu tun hat. Aus den Ausführungen über das Problem bin ich allerdings nicht wirklich schlau geworden, da wären ein paar Zeilen Quelltext oder zumindest Teile davon bestimmt nicht schädlich gewesen. QM hat zwar recht mit seinen Ausführungen, daß nur Komponenten, die zur Laufzeit aus dem Programmcode heraus erzeugt werden (mit NIL als AOwner), später per .Free (oder mit FreeAndNil) im Code wieder freigegeben werden dürfen, aber auch das ist ja laut Snoopy123123 nicht die Ursache.

Ein grundsätzliches Problem der Komponente kann ich ausschließen, dafür ist die bei uns zu häufig im Einsatz. Ohne weitere Infos ist das hier also nur ein Stochern im Nebel.


Gruß Axel
 
Ja, ich kenne dieses eigenartige Verhalten auch. Es hat mich enorm viel Arbeit gekostet, das irgendwie hinzubasteln. Threads, die ich nochmal brauche halte ich an und benutze sie später wieder, völlig weg bekommt man die einfach nicht.
Ganz offen gestanden kann ich das Problem nicht nachvollziehen. Ich habe einige Systemdienste programmiert, die über Wochen und Monate laufen und dabei mehr oder weniger permanent neue Threads erzeugen (einige Threads pro Minute) und wieder beenden, und da bleibt nichts übrig, was nicht völlig weg zu bekommen ist.

Das Hauptproblem beim Verwenden von Threads liegt IMHO darin, daß ein Thread möglichst auf nichts von der VCL zugreifen sollte, was nicht komplett innerhalb des Threads erzeugt wurde. Und mit innerhalb des Threads meine ich ausschließlich in der Execute-Methode, da die Methoden Create und Co. noch innerhalb des Threads aufgerufen werden, in dem die TThread-Klasse instanziert wird.

Und zum Thema Suspend und Terminate:
Suspend legt den Thread schlafen, das ist richtig, aber terminiert wird ein Thread nur, wenn die Execute-Methode verlassen wird. Ein schlafender Thread wird also erst terminiert, nachdem er wieder aufgeweckt wurde. Und Terminate fordert zwar tatsächlich nur die Execute-Methode durch setzen der Terminated-Eigenschaft auf, sich zu beenden, aber für den Code in Execute ist man selbst verantwortlich, und muß dann die Eigenschaft Terminated entsprechend berücksichtigen. Wenn die Execute verlassen wird, wird der Thread dann auch ordnungsgemäß beendet, jedenfalls laut meinen Erfahrungen. Und bei gesetzten FreeOnTerminate wird auch der von TThread belegte Speicher ordentlich wieder freigeräumt.


Gruß Axel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zugriff auf Komponenten oder die Applikation an sich, nehme ich natürlich nur über Synchonize. Ich hatte schon Thread, die sich trotz aller Versuche geweigert haben das OnTerminate-Ereignis zu bringen. 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. Im Moment hab ich einen SQL-Server, der direkt in meine Anwendung integriert ist. Unter bestimmten, nachvollziehbaren Voraussetzungen löse ich da auch eine Exception aus, kann aber nicht herausfinden woran das genau liegt (keine Quellcode, lohnt nicht, den zu kaufen). Aber in einer kleinen Testanwendung passiert das nicht. :confused: Da darf man sich dann einen Wolf suchen, wahrscheinlich hab ich denn auch doch zu wenig Ahnung von den wirklichen Internas von VCL, Delphi, Windows. Aber das will ich ja eigentlich auch gar nicht, dann wär ich C-Programmierer geworden. :ROFLMAO:
 
Das Hauptproblem beim Verwenden von Threads liegt IMHO darin, daß ein Thread möglichst auf nichts von der VCL zugreifen sollte, was nicht komplett innerhalb des Threads erzeugt wurde. Und mit innerhalb des Threads meine ich ausschließlich in der Execute-Methode, da die Methoden Create und Co. noch innerhalb des Threads aufgerufen werden, in dem die TThread-Klasse instanziert wird.
*ACK*

Und zum Thema Suspend und Terminate:
Suspend legt den Thread schlafen, das ist richtig, aber terminiert wird ein Thread nur, wenn die Execute-Methode verlassen wird. Ein schlafender Thread wird also erst terminiert, nachdem er wieder aufgeweckt wurde. Und Terminate fordert zwar tatsächlich nur die Execute-Methode durch setzen der Terminated-Eigenschaft auf, sich zu beenden, aber für den Code in Execute ist man selbst verantwortlich, und muß dann die Eigenschaft Terminated entsprechend berücksichtigen.

immernoch *ACK*

Wenn die Execute verlassen wird, wird der Thread dann auch ordnungsgemäß beendet, jedenfalls laut meinen Erfahrungen. Und bei gesetzten FreeOnTerminate wird auch der von TThread belegte Speicher ordentlich wieder freigeräumt.

Um mal auf wieder auf das andere Thema zu verweisen (http://www.sps-forum.de/showthread.php?p=207828#post207828), 2. Punkt, dass ich das "not Assigned(ReadThread)" habe, das musste ich machen weil der Thread, trotz FreeOnTerminate und FreeAndNil, immernoch irgendwo rumschwirrt, zwar nichts macht, aber irgendwas ist da noch, wie so ein böser Dämon! :ROFLMAO:
 
Um mal auf wieder auf das andere Thema zu verweisen (http://www.sps-forum.de/showthread.php?p=207828#post207828), 2. Punkt, dass ich das "not Assigned(ReadThread)" habe, das musste ich machen weil der Thread, trotz FreeOnTerminate und FreeAndNil, immernoch irgendwo rumschwirrt, zwar nichts macht, aber irgendwas ist da noch, wie so ein böser Dämon! :ROFLMAO:
Zu dem Punkt hab ich mittlerweile in dem entsprechenden Thread eine Antwort geliefert (siehe hier).


Gruß Axel
 
Zurück
Oben