![]() |
Delphi-Version: XE2
TThread.Synchronize
Hallo-
Ich weiß dass schätzungsweise 20% des weltweiten Internet-Traffics von Fragen zu Delphi-Threads und
Delphi-Quellcode:
verursacht werden, trotzdem finde ich nicht wirklich eine Antwort:
Synchronize()
Überall sprechen die Leute nur davon, von einem Thread aus etwas im Kontext des Haupt-Threads auszuführen. Praktisch immer um ein VCL-Element zu aktualisieren. Ich möchte aber vom Hauptthread aus eine Methode im Kontext meines TThread-Objekts aufrufen. Besser noch: Eine lokale Variable auf dem Stack eines Threads A mit Werten füllen die ein Thread B in Erfahrung bringt. In den letzten Tagen wusste ich noch nicht einmal, dass es ein Delphi TThread-Objekt gibt. Bislang bin ich immer direkt den Weg über die WinAPI mittels CreateThread/BeginThread und kritischen Abschnitten gegangen. Jetzt dachte ich, TThread sei unheimlich komfortabel. Ich dachte, ich kann es einfach folgendermaßen über die Bühne bringen:
Delphi-Quellcode:
Das klappt nicht wirklich. Oder zumindest nicht, wie ich mir das vorgestellt habe: Mit diesem Aufruf ist anscheinend keineswegs sichergestellt, dass sich
TThread.Synchronize(
meinThread, procedure begin lokaleVariable := getWert(); end );
Delphi-Quellcode:
nicht auch grade durch
meinThread
Delphi-Quellcode:
wühlt, der darin dann unterbrochen wird, und anschließend der Kram noch einmal obendrauf ausgeführt wird? Denn danach sieht es mir aus...
getWert()
Spontan hätte ich jetzt erwartet, dass
Delphi-Quellcode:
erst einmal so lange blockiert, bis meinThread sich schlafen gelegt hat oder wenigstens nicht selbst gerade mittendrin in getWert() steckt!
TThread.Synchronize(meinThread, ...)
Habe ich durch TThread überhaupt etwas gewonnen? Oder muss ich trotzdem wieder auf kritische Abschnitte und Pipes zurückgreifen? |
AW: TThread.Synchronize
Synchronize wird vom TThread-Objekt aufgerufen, nicht aus dem Hauptthread heraus. Du kannst Daten zwischen den Threads z.B. mittels Events oder Messages austauschen.
|
AW: TThread.Synchronize
Zur Syncronisation habe ich
![]() |
AW: TThread.Synchronize
Hallo -
Ich entschuldige mich für den Sauhaufen an Buchstaben, ich war schon halb durch die Tür. Deswegen hat man wahrscheinlich nicht ganz verstanden, was meine Frage ist. Hoffentlich ist es jetzt klarer. |
AW: TThread.Synchronize
Wichtig ist hierbei auch der Blick in die Dokumentation
![]() Zitat:
Greift dabei auf etwas zu was von einem anderen Threadkontext auch benutzt werden kann, dann kann es knallen. Also entweder alles immer über den Hauptthread synchronisieren (ja, ist doof) oder die Zugriffe mit ![]() Erzähl doch mal, was die Threads machen sollen, evtl. kann man das auch mit ![]() |
AW: TThread.Synchronize
[QUOTE=Der schöne Günther;1207437
Habe ich durch TThread überhaupt etwas gewonnen? Oder muss ich trotzdem wieder auf kritische Abschnitte und Pipes zurückgreifen?[/QUOTE] Na, die Klasse kapselt die Thread-Funktionalität. Du definierst das Verhalten des Threads, also: 1. Wie bzw. womit wird er initialisiert? (Konstruktor) 2. Was soll er im Hintergrund machen? (Execute-Methode) 3. Was soll passieren, wenn er fertig ist. (OnTerminate-Event) Bei Punkt 2 kommt dann die Synchronize-Geschichte ins Spiel. Hiermit kannst Du z.B. Statusanzeigen umsetzen. Wichtig ist hier, das Synchronize so lange wartet, bis der Hauptthread sich drum kümmern kann. Es geht also Zeit flöten. Der Datenaustausch zwischen dem Thread und anderen Threads erfolgt meist über Eigenschaften, deren Setter und Getter mit kritischen Abschnitten (CS) vor konkgruenten Zugriffen schützt. Ein Thread kann einem anderen Thread auch über Messages oder Events mitteilen, das irgend etwas passiert ist (ein Milestone, Zwischenergebnis o.ä.). Der andere Thread holt sich dann die Daten ab (über CS gesichert) und verarbeitet die dann weiter. |
AW: TThread.Synchronize
Vielen Dank für die Antworten! :)
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
.
kümmereDichUmSynchronize-AufrufeVonAnderenThreads()
Um kritische Abschnitte gibt es dann wohl wieder keinen Weg drum herum, ich möchte nicht, dass die Funktion "von außen" aufgerufen/angefordert wird, wenn der Thread selbst auch gerade in dieser Funktion wühlt. Jetzt bin ich mal gespannt, was
Delphi-Quellcode:
bereithält...
TCriticalSection
|
AW: TThread.Synchronize
Was soll
![]() Betreten oder Versuchen zu betreten, Verlassen that's all ;) |
AW: TThread.Synchronize
Und es funktioniert sogar, der Tag ist gerettet.
Im Endeffekt bin ich zwar immer noch etwas ratlos, was für konkrete Vorteile es mir bringt, nicht direkt über die WinAPI zu gehen, aber das wird sich sicher noch zeigen. :thumb: |
AW: TThread.Synchronize
Ich bin von Synchronize mittlerweile ganz weg. Wenn ich im Thread API Ressourcen brauche erstelle ich sie mir dort (nicht als Kompo auf dem Formular z.B.), Threads teilen sich nur via PostMessage mit, und haben Properties deren Getter und Setter mit jeweiligen Critical Sections versehen sind. Zwar wimmelt es in der Thread-Methode je nach Fall von
Delphi-Quellcode:
, aber so muss das Hauptprogramm nachher nicht mehr machen, als die Messages zu emfangen und kann einfach so auf den Feldern des Threads agieren. (Üblicherweise dann Work-Queues und erweiterte Status-Objekte o.ä.)
CS.Enter; try ... finally CS.Leave; end;
Ist etwas mehr Tipperei, aber seit ich das so durchziehe habe ich nie wieder einen Thread gegen die Wand fahren lassen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:27 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-2025 by Thomas Breitkreuz