Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi ListView wird anscheinend vor Destroy-Aufruf zerstört (https://www.delphipraxis.net/31481-listview-wird-anscheinend-vor-destroy-aufruf-zerstoert.html)

sieppl 10. Okt 2004 01:53


ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Hallo,

ich habe einen ListView-Komponente entwickelt die mit einem ThumbnailThread Thumbs aus Bildern generiert und anzeigt. In der ListView.Destroy Routine wird natürlich auch der Thread sauber beendet. Das hat beim Entwickeln der Komponente(dynamisch erzeugt) auch super geklappt. Jetzt soll die Komponente in einem größeren Projekt laufen und ich habe das Problem, dass wenn die Applikation während des Renderns beendet wird der Thread eine Zugriffsverletzung schmeißt, da er nicht mehr auf ListView.Items[x] zugreifen kann. Genau das ist ja eigentlich unmöglich, da der Thread in der Destroy-Routine heruntergefahren werden sollte.
Bei der dynamischen Erzeugung habe ich zum Beispiel in MainForm.Destroy auch ListView.Destroy aufgerufen. Das müsste doch bei den Komponenten automatisch geschehen. Was läuft da falsch???

Viele Grüße

Sebastian

Christian Seehase 10. Okt 2004 02:40

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

ich denke mal ein wenig Sourcecode könnte hilfreich sein.

sieppl 10. Okt 2004 02:48

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Zitat:

Zitat von Christian Seehase
Moin Sebastian,
ich denke mal ein wenig Sourcecode könnte hilfreich sein.

Ich weiß, mache ich auch wann immer möglich. In diesem Fall müsste ich aber große Teile des Codes hier reinstellen und ich glaube, dass ich dann Probleme mit meinem Chef bekomme. :)
Ich hoffe auf einen Referenzfall..

Christian Seehase 10. Okt 2004 02:53

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

Zitat:

Zitat von sieppl
da der Thread in der Destroy-Routine heruntergefahren werden sollte.

oder auch nicht, wie's aussieht ;-)

Hast Du eine Chance das ganze mal im Einzelschritt zu testen?

BTW:
Ich würde statt des Destroy eher Free oder FreeAndNil benutzen.

sieppl 10. Okt 2004 03:06

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Erstmal vielen Dank für deinen Support trotz Code-Verweigerung.

Wie gesagt, liegt der Code nun als Komponente vor und ich rufe
Destroy nicht selber auf, es handelt sich um den überschriebenen Destruktor:

Delphi-Quellcode:
destructor TImgStdListView.Destroy;
begin
  if Assigned(FThumbnailThread) then
  begin
    SuspendThread;
    FThumbnailThread.Terminate;
    FThumbnailThread.Resume;
    WaitForSingleObject(FThumbnailThread.Handle, 3000);
  end;
  if Assigned(FDirWatcherThread) then
  begin
    FDirWatcherThread.Terminate;
    WaitForSingleObject(FDirWatcherThread.Handle, 3000);
  end;
  if Assigned(FCacheList) then
  begin
    ClearTransferList;
    FCacheList.Free;
  end;
  if Assigned(FObjectList) then
    FObjectList.Free;
  if Assigned(FMemoryInfo) then
    FMemoryInfo.Free;
  OleUnInitialize;
  inherited;
end;
Der Thread ist gerade dabei das hier auszuführen wenn der Fehler geworfen wird:

Delphi-Quellcode:
if FListView.Items[I].ImageIndex = 0 then
Nur sollte Items noch vorhanden sein, solange Destroy nicht durchlaufen wurde.
Hat beim Entwickeln auch IMMER funktioniert. auch ohne Synchronize.

Grüße

Sebastian

[EDIT:]
Durchsteppen ist schwierig, da ich auf Anhieb nicht erkenne wann der ListView zerstört wird. Wo geschieht das durch eine Parent-Komponente genau?

Christian Seehase 10. Okt 2004 03:36

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

also ohne Synchronize auf eine VCL-Kompo zuzugreifen ist, genaugenommen, sträflicher Leichtsinn ;-)

Zitat:

Zitat von sieppl
Wo geschieht das durch eine Parent-Komponente genau?

gar nicht, das geschieht durch den Owner.
Der Parent ist nur für die Position zuständig.

An welcher Stelle sollte denn der Listview zerstört werden?

Zitat:

Zitat von sieppl
Erstmal vielen Dank für deinen Support trotz Code-Verweigerung.

Bitte. Es gibt halt Fälle wo's eben nicht geht.

Zitat:

Zitat von sieppl
habe ich zum Beispiel in MainForm.Destroy auch ListView.Destroy aufgerufen.

Zitat:

Zitat von sieppl
ich rufe Destroy nicht selber auf,

:gruebel:

sieppl 10. Okt 2004 03:47

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Zitat:

Zitat von Christian Seehase
Zitat:

Zitat von sieppl
Wo geschieht das durch eine Parent-Komponente genau?

gar nicht, das geschieht durch den Owner.
Der Parent ist nur für die Position zuständig.

An welcher Stelle sollte denn der Listview zerstört werden?

Das möchte ich ja herausfinden, da der ListView anscheinend für Items[I].ImageIndex keinen Wert mehr liefert obwohl Destroy des ListViews noch nicht durchgelaufen ist.

Zitat:

Zitat von Christian Seehase
Zitat:

Zitat von sieppl
habe ich zum Beispiel in MainForm.Destroy auch ListView.Destroy aufgerufen.

Zitat:

Zitat von sieppl
ich rufe Destroy nicht selber auf,

:gruebel:

Zitat:

Zitat von Im 1. Beitrag hat Sieppl geschrieben
Bei der dynamischen Erzeugung habe ich zum Beispiel in MainForm.Destroy auch ListView.Destroy aufgerufen.

Das war während der Entwicklung, jetzt reden wir über eine Komponente. Kein manueller Aufruf von Destroy mehr. (Der besser hätte Free sein sollen)

sieppl 10. Okt 2004 11:33

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Wenn der Zugriff auf Items[I].ImageIndex vom Thread aus synchronized gemacht wird, gibt es dieselbe Zugriffsverletzung. Habe ich mir schon gedacht. (Der Aufruf Items[I].Index befindet sich nun in einer protected-Methode des ListViews.) Nur wenn ich hier vorher
Delphi-Quellcode:
if (csDestroying in ComponentState) then
  Exit;
aufrufe vermeide ich die Zugeiffsverletzung. Das ist nicht optimal und ich verstehe immer noch nicht warum die Items vor dem ListView.Destroy zerstört werden. Kann mir das mal jemand erklären?
Wie gesagt während der Entwicklung der Komponente (dynamische Erzeugung) gab es das Problem einfach nicht.

Christian Seehase 10. Okt 2004 12:55

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

inzwischen sind mir noch ein paar Dinge aufgefallen:
Was macht SuspendThread?
Wozu noch Resume nach Terminate?
Warum verlässt Du Dich, ohne weitere Prüfung, darauf, dass WaitForSingleObject zurückkehrt weil der Thread beendet wurde?
Vielleicht ist der Return Code ja WAIT_TIMEOUT, weil der Thread noch läuft.
Wo wird der ListView erzeugt? In Deine Kompo? In diesem Falle könntest Du als Owner ja nil angeben, und den ListView gezielt nach dem Thread zerstören.

sieppl 10. Okt 2004 13:12

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Zitat:

Zitat von Christian Seehase
Moin Sebastian,

inzwischen sind mir noch ein paar Dinge aufgefallen:
Was macht SuspendThread?

SuspendThread fährt den Thread nach herunter. SuspendThread wartet auch wirklich bis der Thread Suspended ist. (mittels Delay) Das muss so sein, da der Thread Bilder rendert und es manchmal einen Augenblick dauert bis er damit fertig ist.

Zitat:

Wozu noch Resume nach Terminate?
Wenn er Suspended ist (s.o.) muss ich noch einmal fortsetzen damit auch wirklich die while-schleife verlassen wird. (while not terminated do..)

Zitat:

Warum verlässt Du Dich, ohne weitere Prüfung, darauf, dass WaitForSingleObject zurückkehrt weil der Thread beendet wurde?
der Thread wird erfahrungsgemäß innerhalb einer Sekunde beendet. Sollte er mal hängen möchte ich nicht, dass die Applikation nicht beendet wird. (via INFINITE)

Zitat:

Vielleicht ist der Return Code ja WAIT_TIMEOUT, weil der Thread noch läuft.
Wo wird der ListView erzeugt? In Deine Kompo? In diesem Falle könntest Du als Owner ja nil angeben, und den ListView gezielt nach dem Thread zerstören.
Das ist nicht der Punkt, da die Zugriffsverletzung vor dem Destroy-Aufruf erfolgt, bevor die oben erläuterten Methoden aufgerufen werden

Christian Seehase 10. Okt 2004 13:43

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

Zitat:

Zitat von sieppl
Das ist nicht der Punkt, da die Zugriffsverletzung vor dem Destroy-Aufruf erfolgt, bevor die oben erläuterten Methoden aufgerufen werden

Wo der ListView erzeugt wird, und wer der Owner ist, ist, soweit ich das bislang absehen kann, genau der Punkt.
Wenn Du selber die Steuerung übernimmst, wann der ListView zerstört wird, kann er Dir auch nicht vor dem Zerstören des Thread "unter den Füssen weggezogen" werden

sieppl 10. Okt 2004 13:54

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Zitat:

Zitat von Christian Seehase
Moin Sebastian,

Zitat:

Zitat von sieppl
Das ist nicht der Punkt, da die Zugriffsverletzung vor dem Destroy-Aufruf erfolgt, bevor die oben erläuterten Methoden aufgerufen werden

Wo der ListView erzeugt wird, und wer der Owner ist, ist, soweit ich das bislang absehen kann, genau der Punkt.
Wenn Du selber die Steuerung übernimmst, wann der ListView zerstört wird, kann er Dir auch nicht vor dem Zerstören des Thread "unter den Füssen weggezogen" werden

okay, kannst du mir erklären wie ich das steuern kann?
waurm werden denn die Items vor dem Destroy-Aufruf auf nil gesetzt?

Christian Seehase 10. Okt 2004 13:56

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

Zitat:

Zitat von sieppl
waurm werden denn die Items vor dem Destroy-Aufruf auf nil gesetzt?

deshalb meine Frage wann der ListView erzeugt wird, und wer der Owner ist.

sieppl 10. Okt 2004 14:11

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Der ListView wird als Komponente auf das Formular gezogen. Es liegt also nicht direkt in meiner Hand. Ich denke der Owner ist das Panel in dem er drinliegt.

Christian Seehase 10. Okt 2004 14:23

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

das hatte ich befürchtet (und erwartet ;-))

Dann sehe ich (nur) folgende Möglichkeiten:
  • Die Komponente muss dahingehend erweitert werden, dass sie den ListView selber erzeugt.
    (warum heisst die eigentlich TImgStdListView, wenn sie das nicht macht ;-))
  • Deine Kompo wird wieder dynamisch erzeugt.
  • Die Reihenfolge in der die Komponenten auf das Formular gelegt werden wird getauscht.
    Ich weiss es nicht genau, aber das könnte die Reihenfolge in der die Komponenten erzeugt/zerstört werden beeinflussen.

Punkt 2 dürfte wohl mit Abstand am einfachsten umzusetzen sein.

sieppl 10. Okt 2004 15:12

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Zitat:

Zitat von Christian Seehase
Moin Sebastian,

das hatte ich befürchtet (und erwartet ;-))

Dann sehe ich (nur) folgende Möglichkeiten:
  • Die Komponente muss dahingehend erweitert werden, dass sie den ListView selber erzeugt.
    (warum heisst die eigentlich TImgStdListView, wenn sie das nicht macht ;-))
  • Deine Kompo wird wieder dynamisch erzeugt.
  • Die Reihenfolge in der die Komponenten auf das Formular gelegt werden wird getauscht.
    Ich weiss es nicht genau, aber das könnte die Reihenfolge in der die Komponenten erzeugt/zerstört werden beeinflussen.

Punkt 2 dürfte wohl mit Abstand am einfachsten umzusetzen sein.

ja, danke. ich verstehe es aber nicht. der thread wird vom ListView erzeugt und die beiden sind eng miteinander verknüpft. Die ListView.Items können doch nicht einfach verschwinden bevor Destroy aufgerufen wurde.

Christian Seehase 10. Okt 2004 15:49

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Moin Sebastian,

Zitat:

Zitat von sieppl
der thread wird vom ListView erzeugt

:shock: :gruebel:

Also ich hatte es so verstanden, dass der ListView von Dir auf das Formular gezogen wird, und Deine eigene Kompo, die den Thread erzeugt auch. Der ListView wird der anderen Kompo dann übergeben.
Oder nicht, oder doch, oder wie... :gruebel:

sieppl 10. Okt 2004 15:55

Re: ListView wird anscheinend vor Destroy-Aufruf zerstört
 
Zitat:

Zitat von Christian Seehase
Moin Sebastian,

Zitat:

Zitat von sieppl
der thread wird vom ListView erzeugt

:shock: :gruebel:

Also ich hatte es so verstanden, dass der ListView von Dir auf das Formular gezogen wird, und Deine eigene Kompo, die den Thread erzeugt auch. Der ListView wird der anderen Kompo dann übergeben.
Oder nicht, oder doch, oder wie... :gruebel:

:) Der TImgStdListView ist die Kompo über dir wir die ganze Zeit reden. Es handelt sich um einen abgeleiteten ListView. Dieser erzeugt den besagten Thread. (1. Post war schlecht formulitert, sorry)


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz