VCL Main Thread mit verschiedenen RTLs



  • Es gibt ja in jeder VCL Anwendung den MainThread, auf dem die Nachrichtenverarbeitung abläuft (Buttonclicks, etc.). Was passiert jedoch, wenn in einer Anwendung verschiedene RTLs benutzt werden? z.B. wenn das Hauptprogramm mit dem BCB6 erstellt worden wäre und jetzt eine DLL aus einer anderen BCB Version oder gar Delphi einbindet? Laufen dann die Aktionen in der DLL auf dem selben Thread wie in der Hauptanwendung?

    Konkret geht es um asynchrone Socket Events, die von einer Socket Komponente in der DLL empfangen werden und die über Callbacks zu GUI Änderungen in der Hauptanwendung führen. Ich versuche herauszufinden, ob ich diese DLL Events synchronisieren muss.



  • Morle schrieb:

    Es gibt ja in jeder VCL Anwendung den MainThread, auf dem die Nachrichtenverarbeitung abläuft (Buttonclicks, etc.). Was passiert jedoch, wenn in einer Anwendung verschiedene RTLs benutzt werden? z.B. wenn das Hauptprogramm mit dem BCB6 erstellt worden wäre und jetzt eine DLL aus einer anderen BCB Version oder gar Delphi einbindet? Laufen dann die Aktionen in der DLL auf dem selben Thread wie in der Hauptanwendung?

    Konkret geht es um asynchrone Socket Events, die von einer Socket Komponente in der DLL empfangen werden und die über Callbacks zu GUI Änderungen in der Hauptanwendung führen. Ich versuche herauszufinden, ob ich diese DLL Events synchronisieren muss.

    Ziemlich genau die Frage gab es kürzlich mal in den Embarcadero-Newsgroups.

    Das kommt alles darauf an, was die DLL macht. Wenn die DLL ihre eigenen Formulare mitbringt, laufen diese auch im primären Thread; für das Event-Dispatching sorgt Windows (auch wenn es sich dazu der Message-Pump in der VCL der Hauptanwendung bedient). Und natürlich mußt du GUI-Änderungen aus Hintergrundthreads in der DLL genauso behandeln wie in der Anwendung selbst.



  • D.h. wenn ich keine Formulare in der DLL verwende, dann muss ich synchronisieren? In der DLL gibt es nämlich keine, es wird nur irgendwo mal ein TClientSocket instanziiert. Ist die Verbindung aufgebaut soll z.B. ein Label in der Hauptanwendung geändert werden (um anzuzeigen, dass die Verbindung jetzt besteht), etc.
    Ich habs jetzt sowieso synchronisiert, aber ich würde es gerne allein schon aus Interesse genau wissen, wie sich das verhält. Wieso machen z.B. Formulare einen Unterschied? Ich dachte, die Socket Komponente verwendet intern irgendein unsichtbares Fenster.



  • Morle schrieb:

    Ist die Verbindung aufgebaut soll z.B. ein Label in der Hauptanwendung geändert werden (um anzuzeigen, dass die Verbindung jetzt besteht), etc.

    Wenn die DLL eine andere VCL- und Compilerversion verwendet, dann darfst du von dort überhaupt nicht auf irgendein Label der Hauptanwendung zugreifen. Ich hoffe, du bist dir darüber im klaren.

    Synchrnisieren mußt du dann, wenn du aus einem Hintergrundthread auf das UI zugreifst, und es ist egal, ob der Hintergrundthread zu einer DLL gehört oder nicht, ob er dieselbe Version der VCL verwendet oder nicht etc. Zugriffe auf UI-Elemente der VCL aus einem anderen als dem primären Thread sind schlicht nicht erlaubt.



  • audacia schrieb:

    Wenn die DLL eine andere VCL- und Compilerversion verwendet, dann darfst du von dort überhaupt nicht auf irgendein Label der Hauptanwendung zugreifen. Ich hoffe, du bist dir darüber im klaren.

    Ja natürlich. Von der DLL rufe ich eine Callbackfunktion in der Hauptanwendung auf. Diese ändert dann ggf. das Label. Ich muss nur sicher gehen, dass der Callback aus der DLL auf dem gleichen Thread ausgeführt wird, der auch sonst die GUI Änderungen in der Hauptanwendung machen würde (das ist ja meine Frage).

    Synchrnisieren mußt du dann, wenn du aus einem Hintergrundthread auf das UI zugreifst, und es ist egal, ob der Hintergrundthread zu einer DLL gehört oder nicht, ob er dieselbe Version der VCL verwendet oder nicht etc.

    Auch richtig. Nur verwende ich ja keine Threads. Es handelt sich ja um eine Socket Komponente, d.h. wenn Daten gelesen werden geht ja zu nächst eine Windows-Nachricht ein und irgendwann wird dann das Ereignis OnClientRead der Socket-Komponente ausgelöst. Deswegen muss man Zugriffe auf die GUI aus OnClientRead nicht synchronisieren, denn OnClientRead wird ja gerade eben aus der Nachrichtenbehandlung aus ausgeführt (und damit auf dem VCL Thread) und daher sind Änderungen an der GUI von anderswo zu dem Zeitpunkt ja nicht möglich.

    Zugriffe auf UI-Elemente der VCL aus einem anderen als dem primären Thread sind schlicht nicht erlaubt.

    Was mich wieder zu meiner ursprünglichen Frage bringt: Erstellt jede RTL seinen eigenen Thread oder verwendet die RTL in der DLL z.B. aufgrund irgendwelcher Windows Interna den Hauptthread der Anwendung.



  • Morle schrieb:

    Ich muss nur sicher gehen, dass der Callback aus der DLL auf dem gleichen Thread ausgeführt wird, der auch sonst die GUI Änderungen in der Hauptanwendung machen würde (das ist ja meine Frage).

    Wenn du sichergehen mußt, dann mache lieber ein Synchronize().

    Auch richtig. Nur verwende ich ja keine Threads. Es handelt sich ja um eine Socket Komponente, d.h. wenn Daten gelesen werden geht ja zu nächst eine Windows-Nachricht ein und irgendwann wird dann das Ereignis OnClientRead der Socket-Komponente ausgelöst. Deswegen muss man Zugriffe auf die GUI aus OnClientRead nicht synchronisieren, denn OnClientRead wird ja gerade eben aus der Nachrichtenbehandlung aus ausgeführt (und damit auf dem VCL Thread) und daher sind Änderungen an der GUI von anderswo zu dem Zeitpunkt ja nicht möglich.

    Wenn OnClientRead() nachweislich immer im Haupt-Thread ausgeführt wird, brauchst du eben kein Synchronize().

    Erstellt jede RTL seinen eigenen Thread oder verwendet die RTL in der DLL z.B. aufgrund irgendwelcher Windows Interna den Hauptthread der Anwendung.

    Habe ich oben doch geschrieben: was Windows-Messages in der VCL angeht, sollten alle DLLs denselben primären Thread benutzen.

    Wenn du im Zweifel bist, probiere es doch einfach aus.


Anmelden zum Antworten