Synchronisation Callback mit MainForm
-
OK das war ja nur ein Beispiel
Nehmen wir ein anderes ich öffne einen COM Port und lese mit Readfile und Overlapped und einem Callback.
Wie Synchronisiere ich den mit dem Form?
-
Zum Beispiel mit eienr TCriticalSection. Aber ich bevorzuge die WinAPI-Variante, weil man dort überprüfen kann, ob man synchronisieren kann. Bei der VCL-Variante hat man diese Möglichkeit nicht, dort wird grundsätzlich gewartet, bis synchronisiert werden kann. Bei der WinAPI-Variane kann man an dieser Stelle abbrechen und den Thread weiterarbeiten lassen (sofern es noch was zu tun gibt und die Synchronisation zu diesem Zeitpunkt nicht obligatorisch ist).
Gruß KK
-
Wenn ich die Daten aus dem Callback in Variablen schreibe und ein anderer Thread die entgegennimmt. Weiß ich wie ich das mache.
Meine Frage ist gibt es noch eine andere Möglichkeit mit dem Form zu Synchronisieren außer Synchronize?
Kann ich irgenwie erkennen das ich nichts am Form ändern darf in einem bestimmten Moment?
-
Wenn ich deine letzten Frage nicht falsch verstanden habe, glaube ich du hast den Grund warum man Synchronize benutzen MUSS nicht ganz verstanden:
Du hast 2 Threads die etwas tun, der eine ließt Daten, der andere gibt sie aus. Die beiden können aber nicht gleichzeitig auf der CPU arbeiten, sondern machen das immer nacheinander, mal der eine ne Millisekunde, mal der andere.
Wenn nun einer der Threads in einem ungünstigen Moment vom Scheduler unterbrochen wird, kann es sein, das der andere mit nicht-gültigen(weil unvollständig bearbeitete) Daten arbeitet, oder Daten ändern, auf die der andere Thread sich gerne noch berufen hätte.Heißt also wenn du den VCL-Thread mitten im Neuzeichnen mit neuen Daten störst, kann es zu undefiniertem Verhalten kommen.
Also benutzt man Synchronize um dem VCL-Thread mitzuteilen, das man gerade mal ein paar Millisekunden seiner Aufmerksamkeit benötigt, um in der Zeit die Daten des Threads zu manipulieren.
Also lautet die Antwort auf deine Frage, wie man erkennt das man ein Form nicht ändern darf: Wenn du Threads benutzt!
mfg
xXx
-
Also komm ich nicht darum herum das der Callback einen Thread erzeugt der dann wiederum über Synchronize im Form die Änderung vornehmen kann, da der Callback ja Synchronisze nicht kennt.
Oder gibt es eine andere Funktion die Ebenfalls das Verhalten von Synchronize hat die ich aber aus dem Callback benutzen kann?
Denn wenn ich so 100 verschieden Callbacks habe ist das doch ein bischen aufwendig für jeden einen Thread bauen die jeweilige Methode bauen die mit Synchronize aufgerufen. Sowie einen haufen globaler Veriablen um die Daten vom Callback in den Thread zu schaffen.
MfG
-
Du brauchst Synchronize ja nur, wenn du Steuerelemente ändern willst. Wenn du Daten bearbeiten willst, musst du nur den Zugriff auf diese durch z.B. TCriticalSection schützen. Auszug aus der BDS2006 Hilfe:
Mit TCriticalSection können Operationen abgesichert werden, die nicht durch den Ausführung eines bestimmten Codeabschnitts durch einen anderen Thread unterbrochen werden dürfenCallback wird aufgerufen, CriticalSection wird betreten, Daten werden verwurschtet, evtl. Repant-Message an ein Fenster senden, CriticalSection wird verlassen
mfg
xXx
-
Also wenn ich Checkboxen oder Buttons usw. verändere, muss ich Synchronisze benutzen.
Bei Editfeldern, Statusfeldern, StringGrids oder Memos usw. brauche ich Synchronize nicht?
ist das auch so wenn ich ein EditFeld aktiviere/deaktiviere?
-
Destiniy schrieb:
Bei Editfeldern, Statusfeldern, StringGrids oder Memos usw. brauche ich Synchronize nicht?
Selbstverständlich brauchst Du auch dafür Synchronize, selbst wenn du nur lesend darauf zugreifst.
Destiniy schrieb:
ist das auch so wenn ich ein EditFeld aktiviere/deaktiviere?
Ich denke die Frage kannst du nun selbst beantworten...
Gruß KK
-
So wie sich das anhört willst du ja ziemlich viel im Callback ändern. Würde ich aber nicht tun.
Mein Gedanke: Speicher das, was du durch den Callback bekommst in einer Datenstruktur (durch CriticalSection geschützt), die für die Formulare sichtbar ist, die diese Daten anzeigen sollen.
Dann sende eine selbst gemachte Botschaft an das Fenster, das landet in der Queue und wird Threadsafe abgearbeitet. Wenn das Fenster die Botschaft erhält, lässt du alle Label, Edits etc aktualisieren.Als Hinweis fürs Verständnis: Es gibt einen Thread, der alle Fenster (und deren Steuerelemente) beinhaltet und neu zeichnet etc, der VCL-Thread. Andere Threads müssen mit dem synchronisieren, wenn sie irgendwas in der VCL machen (sichtbare wie unsichtbare Komponenten.
mfg
xXx
-
-=]xXx[=- schrieb:
Mein Gedanke: Speicher das, was du durch den Callback bekommst in einer Datenstruktur (durch CriticalSection geschützt), die für die Formulare sichtbar ist, die diese Daten anzeigen sollen.
Dann sende eine selbst gemachte Botschaft an das Fenster, das landet in der Queue und wird Threadsafe abgearbeitet. Wenn das Fenster die Botschaft erhält, lässt du alle Label, Edits etc aktualisieren.Oh je, dass wollte ich eigentlich für später aufheben... Aber dann sollte man an dieser Stelle gleich noch Events erwähnen. Da er im Thread sowieso schon mit WaitForSingleObject arbeiten muss, um die Daten vom COM-Port abzurufen, kann man mit Events und mit WaitForMultipleObjects den Thread prima steuern.
Also zusammengefasst: Um Aktionen im VCL-Thread auszulösen, Botschaften aus dem Thread heraus senden und um Aktionen im Workerthread auszulösen, entweder Events verwenden, oder ebenfalls Botschaften verwenden. Hängt von der Arbeitsweise des Workerthreads ab. Im Falle des COM-Port-Beispiels wären Events die sinnvollere Lösung.Gruß KK