Ich habe ein Problem, dass der Code in meiner DLL anders funktioniert als der gleiche Code in einer normalen Anwendung. Nach einigen Debugging habe ich festgestellt, dass der OnTerminate des Threads nie innerhalb der DLL aufgerufen wird.
%Vor%Wenn ich diesen Code von einer normalen VLC Delphi-Anwendung aus starte, bekomme ich end in der Textdatei. Wenn ich denselben Code von einer DLL aus starte (entweder statisch oder dynamisch in eine VLC-Anwendung geladen), bekomme ich start in der Textdatei.
Meine Frage: Warum? Oder besser gefragt, wie kann ich meine dll so verhalten wie meine VLC. Aktuelle Version, die ich verwende, ist XE7.
Das Ereignis TThread.OnTerminate
wird im Kontext des Hauptthreads der Benutzeroberfläche über einen Aufruf von TThread.Synchronize()
ausgelöst, der Anforderungen in einer Warteschlange speichert, die der Haupt-UI-Thread regelmäßig überprüft und ausstehende Anforderungen ausführt, sofern verfügbar.
Wenn DLL und EXE mit aktivierten Laufzeitpaketen kompiliert werden, teilen sie sich eine einzelne Kopie der RTL (und erfordern daher, dass Sie rtl.bpl
mit Ihrer App bereitstellen). Wenn die EXE die Synchronize()
-Warteschlange der RTL überprüft, werden ausstehende Anfragen von EXE und DLL angezeigt.
Wenn sie jedoch keine einzelne RTL teilen, werden sie mit separaten Kopien der RTL kompiliert, die nicht miteinander verknüpft sind. Standardmäßig befindet sich in der EXE nichts, das ausstehende Anfragen aus der Synchronize()
-Warteschlange der DLL prüft und verarbeitet, sondern nur aus der Warteschlange Synchronize()
der EXE. Um dies zu beheben, müssen Sie eine Funktion aus der DLL exportieren, die die CheckSynchronize()
-Funktion der DLL-RTL aufruft, und dann den EXE-Aufruf durchführen, der die DLL-Funktion in regelmäßigen Abständen exportiert, beispielsweise in einem Timer.
Anderenfalls besteht die andere Möglichkeit, dieses Problem zu umgehen, darin, den Aufruf Synchronize()
zu umgehen, der das Ereignis OnTerminate
auslöst, indem die virtuelle Methode DoTerminate()
des Threads überschrieben wird (was mit TThread.CreateAnonymousThread()
nicht möglich ist). Sie können DoTerminate()
call OnTerminate
direkt haben oder einfach tun, was Sie innerhalb von DoTerminate()
selbst benötigen. Wie auch immer, Sie müssen sicherstellen, dass dieser Code Thread-sicher ist, da DoTerminate()
im Kontext des Worker-Threads ausgeführt wird.