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 Problem mit Dll & Threads (https://www.delphipraxis.net/146529-problem-mit-dll-threads.html)

Assertor 21. Jan 2010 18:41


Problem mit Dll & Threads
 
Hallo DPler,

jetzt brauche ich mal nach langem mal wieder selbst Denkhilfe & Brainstorming:

Ich habe hier ein DLL Projekt liegen (Delphi 2010). Die Exporte dafür müssen so bleiben. Intern verwendet die DLL Threads und bei bestimmten Vorgängen zeigt diese VCL Forms. Technisch gesehen soweit, so schlecht.

Jetzt gibt es beim Aufräumen des ThreadPool einen schönen DeadLock. Die Stelle ist

Delphi-Quellcode:
for i := 0 to Length(FThreadPool) - 1 do
begin
  // FThreadPool[i].FreeOnTerminate := True; // soft shutdown
  FThreadPool[i].Terminate;
  FThreadPool[i].WaitFor; // <- freezes
  FThreadPool[i].Free; // <- freezes
end;
Die oben markierten Stellen führen zum DeadLock, aber nur wenn der Pool in der Finalisierung einer Unit aufgeräumt wird. Ich sehe da verschiedene Probleme mit Threads und DLLs im Bereich Finalisierung.

Was haltet Ihr davon nun ein Semaphore/Event nach Execute zu nutzen, um im Destruktor zu warten (.WaitFor) bis dies eingetreten ist, um danach FreeOnTerminate zu setzten? Also sozusagen von Serialized Shutdown auf Soft-Shutdown umstellen?

Ohne Soft-Shutdown gibt es den MessageQueue DeadLock, mit laufe ich Gefahr das die Finalisierung der Units wie z.B. Classes vor Ende der Threads bereits durchlaufen wurde... Deswegen ein Event. Irgendwie "smellt" der Code, aber das ist das sauberste was mir einfällt bei Beibehaltung der Exporte.

Zweites Problem, gleicher Zusammenhand:

Die Thread zeigen VCL Forms, also müssten diese Synchronisiert werden. Aber womit ;) Mir ist bekannt, das es da Probleme geben kann mit Threads in DLLs und Synchronize. Threads deswegen, da Hintergrundprüfungen und TCP/IP Übertragungen vorgenommen werden. Also etwas, was nicht im Mainthread-Context laufen sollte.

Vorschläge? Ideen?

Gruß Assertor

Edit1: Offene Frage draus gemacht
Edit2: Delphi Version

wicht 21. Jan 2010 19:02

Re: Problem mit Dll & Threads
 
Muss man denn das Form der DLL in einem eigenen Thread erstellen? Ich meine sowas auch mal gemacht zu haben, da konnte ich ganz normal in der der DLL das Fenster anzeigen (kann sein, dass es Modal war, aber tut das was zur Sache?). Und wenn das gehen sollte, wäre das ja ein Zeichen dafür, dass die Forms-Unit sich um einen MessageLoop in eigenem Thread kümmert und du könntest Synchronize eventuell verwenden?
Mit WaitFor und Terminate habe ich auch schon tolle Erfahrungen gesammelt. Hilft dir vielleicht die OnThreadTerminated-Property? Ich habe meinen Kram auf FreeOnTerminate := True, mache in dem Ereignis die abschließenden Arbeiten und der Thread gibt sich dann selbst Frei. An anderer Stelle setze ich am Ende von Execute ein Event auf welches ich warte, ist denke ich auch nicht verkehrt (hast du ja schon selbst vorgeschlagen).

Vielleicht hilft das irgendwie minimal weiter...

Assertor 21. Jan 2010 19:09

Re: Problem mit Dll & Threads
 
Hi wicht,

danke für die schnelle Antwort :)

Zitat:

Zitat von wicht
Muss man denn das Form der DLL in einem eigenen Thread erstellen? Ich meine sowas auch mal gemacht zu haben, da konnte ich ganz normal in der der DLL das Fenster anzeigen (kann sein, dass es Modal war, aber tut das was zur Sache?). Und wenn das gehen sollte, wäre das ja ein Zeichen dafür, dass die Forms-Unit sich um einen MessageLoop in eigenem Thread kümmert und du könntest Synchronize eventuell verwenden?

Ja, das sind nur modale Sachen, da wird natürlich zum Glück nichts an VCL über die Boundaries geschoben.

Jetzt ist es so: Workerthreads arbeiten und erstellen & zeigen Modales Fenster wenn nötig (das dann synchronisiert).

Zitat:

Zitat von wicht
Mit WaitFor und Terminate habe ich auch schon tolle Erfahrungen gesammelt. Hilft dir vielleicht die OnThreadTerminated-Property? Ich habe meinen Kram auf FreeOnTerminate := True, mache in dem Ereignis die abschließenden Arbeiten und der Thread gibt sich dann selbst Frei. An anderer Stelle setze ich am Ende von Execute ein Event auf welches ich warte, ist denke ich auch nicht verkehrt (hast du ja schon selbst vorgeschlagen).

Vielleicht hilft das irgendwie minimal weiter...

Auf jeden Fall, das Event am Ende von Execute war genau meine Idee - von daher ist das ja schonmal eine Bestätigung.

Edit: VCL in DLL hat ja eigenen Scope, also sollte das kein Problem sein. Das die VCL nicht thread-safe ist, bedeutet für eine autarke DLL nicht, das diese nicht in einem Thread ausgeführt werden kann. Nur die Grenzen sind wichtig, das Synchronize geht naütrlich nicht, da es ohne Applikation kein positives Resultat für CheckSynchronize gibt, mangels MessageQueue.

Mal gucken, was mir da noch einfällt...

Edit2: Gelöst, für das Terminate geht natürlich das Event, für das Synchronize den guten alten Fix von Peter Below (TeamB, so wie unser Remy vom Indy Team). Link: http://cc.embarcadero.com/Item.aspx?id=21148. Der D6DLLSynchronizer macht nichts anderes, als der DLL eine globale MessageQueue zu geben, was CheckSynchronize im Thread und damit Synchronize() wieder funktionieren lässt.

Darauf hätt ich kommen können... Trotzdem vielen Dank :)

Gruß,

Assertor


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:42 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