Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben (https://www.delphipraxis.net/145091-von-threada-erzeugtes-vcl-objekte-von-threadb-freigeben.html)

s.h.a.r.k 23. Dez 2009 13:19


Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Hallo zusammen,

und zwar habe ich gerade ein interessantes Problem, auf welches ich absolut keine Antwort habe. Und zwar habe ich eine Controller-Klasse, in der alle Referenzen auf erzeugte Objekte gehalten werden. Beim Start meiner Anwendung erzeuge ich zunächst einen SplashScreen und einen weiteren Thread. Im SplashScreen läuft eine GIF-Animation ab und der Thread erzeugt alle nötigen Objekte -- teilweise auch VCL-Objekte, wie TListBox -- und macht sonst auch noch ein paar Sachen. Zugriff auf den Splash Screen mache ich nicht direkt aus dem Thread, sondern schicke via PostMessage immer Nachrichten, sodass der SplashScreen aktualisert wird.

Beim Beenden der Anwendung will ich eine ListBox freigeben, welche in einer Methode erzeugt wurde, die vom Startup-Thread aufgerufen wurde. Nun ist es aber so, dass genau da ein Systemfehler. 1400 Ungültiges Handle erhalte und das Programm abbricht. Als ich noch nicht die Lösung mit dem Thread angestrebt hatte, lief alles problemlos.

Ich verstehe nicht ganz, warum dieser Fehler auftritt? Wenn das Programm fertig geladen ist, dann hält doch nur noch nur noch der Controller alle Referenzen, der Thread ist freigegeben und ein FreeAndNil müsste doch funktionieren? Oder wird beim freigeben des Threads die ListBox auch freigegeben, da diese im Kontext des Thread erzeugt wurde?

mfg
*schwimm*

Bernhard Geyer 23. Dez 2009 13:29

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
As Designed. Windows GUI-Handles haben eine Thread-Affinität. Diese dürfen nur im erzeugenden Thread verwendet werden! Nicht umsonst ist die VCL nicht Thread-Save.

Alle Zugriffe (erzeugen, verwenden, freigeben) nur im Hauptthread durchführen. Ansonsten gibt es problem wenn Listbox von Thread X erzeugt wurde aber der parent vom Thread Y -> Kracht an allen möglichen stellen.

s.h.a.r.k 23. Dez 2009 13:31

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
d.h. wenn ich z.B. eine ListBox in einem Thread erzeuge, dann *ausschließlich* dort schreiben und freigeben, richtig?

Wie sieht das mit Lesen aus?

PS: Muss ich auch einen synchronisierten Aufruf machen, wenn ich eine Eigenschaft einer VCL-Komponente ändere?

Bernhard Geyer 23. Dez 2009 13:33

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Zitat:

Zitat von s.h.a.r.k
d.h. wenn ich z.B. eine ListBox in einem Thread erzeuge, dann *ausschließlich* dort schreiben und freigeben, richtig?

Ja
Zitat:

Zitat von s.h.a.r.k
Wie sieht das mit Lesen aus?

Genauso. Es wird ja auch hier bei diversen Property-Abfragen das Windows-Handle benötigt.

sirius 23. Dez 2009 13:34

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Am besten ist Regel Nummer 1:
Sichtbare Objekte (VCL) nur im MainThread beutzen.

s.h.a.r.k 23. Dez 2009 13:43

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Zitat:

Zitat von s.h.a.r.k
PS: Muss ich auch einen synchronisierten Aufruf machen, wenn ich eine Eigenschaft einer VCL-Komponente ändere?

Hatte noch eine Änderung an meinem obigen Post gemacht ;) Wohl etwas zu spät, wie ich gesehen hatte. Aber ich gehe einfach mal davon aus, dass die Änderungen auch synchronisiert erfolgen müssen.

Danke für eure Antworten schon mal :thumb:

PS: Ein beliebiger Thread selbst aber schon ein VCL-Objekt erzeugen, darauf arbeiten und dann wieder zerstören, oder? Alle Aurufe bleiben eben in dem einen Thread.

Reinhard Kern 23. Dez 2009 15:21

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Zitat:

Zitat von s.h.a.r.k
PS: Ein beliebiger Thread selbst aber schon ein VCL-Objekt erzeugen, darauf arbeiten und dann wieder zerstören, oder? Alle Aurufe bleiben eben in dem einen Thread.

Hallo,

du weisst nicht, wie die VCL-Objekte untereinander verwoben sind - z.B. könnte deine Listbox ein Handle auf den Canvas brauchen, aber der ist in einem anderen Thread. Ich würde daher sagen, es funktioniert zumindest nicht immer, also Finger weg. Ausserdem brauchst du ja schon zum Erzeugen das Parent-Handle usw.

Gruss Reinhard

s.h.a.r.k 23. Dez 2009 15:28

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Ich habe allerdings in meiner Datenbank-Klasse eine Form, welche modal aufgerufen wird, wenn was mit der Verbindungs nicht klappt. Diese Form hat als Owner nil und braucht doch keinen Parent, oder? In diesem Fall hat jedenfalls alles geklappt.

himitsu 23. Dez 2009 15:36

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Die VCL nutzt intern viele gemeinsame Resourcen ... also ist es nicht grad sicher, daß es über Threadgrenzen hinweg nie Probleme gibt.

sirius 23. Dez 2009 15:38

Re: Von ThreadA erzeugtes VCL-Objekte von ThreadB freigeben
 
Meine Erfahrung sagt, dass auch dies nicht geht.

GEnau das hatte ich auch einmal in einem Programm gemacht. Der Hauptteil besand darin, dass man nur "quasi" Unterprogramme aufruft, welche ein eigenes Fenster haben und es gibt auch sonst keine Überschneidungen. Dazu wollt ich diese Unterprogramme auch komplett in einen eigenen Thread legen. --> ging nicht und ergab plötzliche zufällige Fehler (besonders im Aussehen der Formulare)


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:56 Uhr.
Seite 1 von 2  1 2      

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