Auf Synchronize warten

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
marcov
Beiträge: 1102
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: Auf Synchronize warten

Beitrag von marcov »

Patito hat geschrieben:
Etwas irritierend ist nur, dass man beim RTLeventWaitFor mit Timeout keine Rückmeldung kriegt,
ob das Event gekommen ist, oder ob man in den Timeout gerannt ist.
- Tevent hat eine Rückgabe
- TEvent nutzt aber basiceventwaitfor der auch eine Rückgabe hat
- basiceventwaitfor ist aber deprecated und man soll RtlEventWaitFor nutzen, der ist aber nutzlos ohne Rückgabe .

... bitte tragen Sie das alle als als Bug ein in Mantis :D

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Auf Synchronize warten

Beitrag von Patito »

marcov hat geschrieben: ... bitte tragen Sie das alle als als Bug ein in Mantis :D
Ja. Timeouts funktionieren eben nicht richtig - ohne Timeout scheint alles so weit zu funktionieren.
Als Ersatz für die nicht funktionierenden Events habe ich früher unter Linux CriticalSections genommen, aber da gibt es weitere Probleme.

In manchen APIs sind Critical Sections "reentrant", was sie als Ersatz für Events eher unbrauchbar macht.
(man kann Ressourcen schützen, aber ohne aktives pollen kann man damit nicht so einfach kommunizieren).

Irgendwo habe ich gelesen, dass jemand die Critical Sections in FPC aus konsistenzgründen alle reentrant gemacht hat.
Was sie dann wohl als Ersatz für TEvent unter Linux weniger brauchbar macht...

Das Problem mit reentrant CS kann man in dem Code-Fragment von Warf grob erkennen.

Thread A: CS.Create
Thread A: CS.Enter (wartet darauf, dass Thread B die CS freigibt)
Thread B: Im Execute kommt irgendwann CS.Enter.
Thread A muss also erst darauf warten, dass Thread B im Execute den Code mit dem CS.Enter erreicht hat, bevor er auf die CS warten kann
... wozu man wieder ein anderes Event braucht... wozu man eine CS braucht, die ein Event braucht, ....
-> das funktioniert so nicht
(Als Fix das CS.Enter in den Konstruktur von Thread B zu verschieben hilft vermutlich auch nicht, da der Konstruktor im Kontext von Thread A läuft,
was bei reentrant-CS dazu führt, dass Thread A beim CS.Enter dann überhaupt nicht mehr blockiert)

Was man als Ersatz für ein Event bräuchte, wäre so etwas:
Thread A: CS.Enter
Thread A: CS.Enter (wartet darauf, dass jemand anderes CS.Leave aufruft)
Thread B: CS.Leave
Thread A: macht weiter

Mit reentrant CS kriegt man Events so leider nicht hin.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Auf Synchronize warten

Beitrag von mschnell »

Patito hat geschrieben:Irgendwo habe ich gelesen, dass jemand die Critical Sections in FPC aus konsistenzgründen alle reentrant gemacht hat.
Was sie dann wohl als Ersatz für TEvent unter Linux weniger brauchbar macht...
Gut zu wissen !!!

Ist das irgendwo dokumentiert ?


Der OP wollte allerdings anscheinend "im Mainthread warten". und zwar anscheinend längere Zeit. Dafür sind CS aber sowieso ungeeignet. Hier ist eine Signalisierung mit TThread.Synchronize, TThread.Queue oder Application.QueuAsyncCall die einzige sinnvolle Möglichkeit. Man muss die Programm-Struktur natürlich entsprechend gestalten.

-Michael

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Auf Synchronize warten

Beitrag von Patito »

mschnell hat geschrieben: Der OP wollte allerdings anscheinend "im Mainthread warten". und zwar anscheinend längere Zeit. Dafür sind CS aber sowieso ungeeignet. Hier ist eine Signalisierung mit TThread.Synchronize, TThread.Queue oder Application.QueuAsyncCall die einzige sinnvolle Möglichkeit. Man muss die Programm-Struktur natürlich entsprechend gestalten.
Oder man wartet im Mainthread in einer Schleife auf ein Event und verwendet recht kurze Timeouts (1 Sekunde sollte reichen).
Von der Struktur her sind Events mit Timeout im Mainthread bestimmt wesentlich einfacher als irgendwelche per Synchronize gesetzte Flags, die
man anlegen, schützen und auch noch aktiv überwachen muss.

Alles rund um Synchronize halte ich für Gebastel aus der Steinzeit von Delphi. Wenn schon ein Managerthread, dann bitte ein richtiger und nicht
gerade der Mainthread (der auch schon mal wegen der GUI zum Spaß die Kommunikation verzögern kann). So ein Managerthread ist aber immer ein
potentieller Flaschenhals, und blockiert eventuell einen ganzen Kern.

In den User Changes zu FPC 3.0 steht etwas zu re-entrant drin. Ich meine mich zu erinnern, dass die CriticalSections vor langer Zeit mal
unter Linux so funktioniert haben wie ich es erwartet hatte, mit einem aktuellen Lazarus mit 2.6.x unter Linux hatte ich aber Probleme.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Auf Synchronize warten

Beitrag von Socke »

Patito hat geschrieben:In den User Changes zu FPC 3.0 steht etwas zu re-entrant drin. Ich meine mich zu erinnern, dass die CriticalSections vor langer Zeit mal
unter Linux so funktioniert haben wie ich es erwartet hatte, mit einem aktuellen Lazarus mit 2.6.x unter Linux hatte ich aber Probleme.
Siehe hier: http://wiki.freepascal.org/User_Changes ... ex_support
Die Änderung bezieht sich also nur auf cthreads.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Auf Synchronize warten

Beitrag von mschnell »

Patito hat geschrieben:Oder man wartet im Mainthread in einer Schleife
Man kann natürlich an jedem System vorbei-programmieren. Man kann auch alles in Assembler schreiben.

Halte ich aber nicht für besonders sinnvoll und sollte im Forum nicht unterstützt werden.
Patito hat geschrieben:Alles rund um Synchronize halte ich für Gebastel aus der Steinzeit von Delphi.
Quatsch !
Die Programmier-Methodik heißt "Event-Orientierte Programmierung". Man muss sich natürlich (genau wie bei "Objekt-Orientierter Programmierung") darauf einlassen (wollen) um sie sinnvoll zu benutzen.

Unbedingt nötig ist das natürlich nicht, Da Lazarus aber für das ganze User-Interface mit Event-Orientierte Proigrammierung (im Main Tread) erzwingt, ist es natürlich sinnvoll, auch die Thread->Mainthread Signalisierung in dieser Art zu realisieren. Alles andere führt auf Dauer ins Chaos.

Ein historisches Problem ist, das es TThread.Queue erst seit Delphi 7 gibt und es erst ab Delphi XE dokumentiert ist (und dass es in fpc erst "offiziell" ab Version 3.0 existiert, vermutlich da Lazarus - anders als Delphi - mit Appliction.QueueAsyncCall immer schon eine portable Alternative hatte) und deshalb TThread.Queue wenig bekannt ist.

Mit "Manager Thread" hat das wenig zu tun. Der Main Thread macht zwingend das GUI Interface und muss deshalb oft anzeigen oder beeinflussen, was in den Worker-Threads passiert. Der Main Thread krankt natürlich daran, dass dort alle GUI Events bearbeitet werden müssen und die Latenz deshalb höher ist als in Worker Threads. Anwendungen, wo man wirklich einen High-Performance Manager Thread braucht, sind aber eher selten.

Ich finde es im Gegenteil ausgesprochen schade, dass man in Worker Thrfeads nicht Event-Orientiert programmieren kann und Lazarus (ganau wie Delphi) für Worker Threads alsao eine ander Progreammier-Logik erzwingt als im Main Thread notwendig und üblich ist. In mse-ide isat es - soweit ich weiß - möglich, für Worker-Threads eine Event-Queue zu definieren und auch dort Event-orientiert zu arbeiten.

-Michael

-Michael

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Auf Synchronize warten

Beitrag von Socke »

mschnell hat geschrieben:Ein historisches Problem ist, das es TThread.Queue erst seit Delphi 7 gibt und es erst ab Delphi XE dokumentiert ist (und dass es in fpc erst "offiziell" ab Version 3.0 existiert, vermutlich da Lazarus - anders als Delphi - mit Appliction.QueueAsyncCall immer schon eine portable Alternative hatte) und deshalb TThread.Queue wenig bekannt ist.
Gibt es eine Dokumentation zu den verschiedenen Methoden und deren Unterschiede?
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Auf Synchronize warten

Beitrag von mschnell »

Socke hat geschrieben:Gibt es eine Dokumentation zu den verschiedenen Methoden und deren Unterschiede?
Kurzform:

TThread.Queue:
Die Ereignis-Methode wird zur Verarbeitung im Mainthread vorgemerkt. Der Mainthread wird sie bearbeiten, wenn alle vorher angeworfenen Ereignisse bearbeitet worden sind.

TThread.Synchronmize:
Die Ereignis-Methode wird zur Verarbeitung im Mainthread vorgemerkt. Der Mainthread wird sie bearbeiten, wenn alle vorher angeworfenen Ereignisse bearbeitet worden sind. Der aufrufenden Thread wartet bis der Mainthread die Ereignis-Methode fertig ausgeführt hat.

Application.QueuAsyncCall:
TThread.Queue:
Die Ereignis-Methode wird zur Verarbeitung im Mainthread vorgemerkt. Der Mainthread wird sie bearbeiten, wenn alle vorher angeworfenen Ereignisse bearbeitet worden sind. Man kann zusätzlich zu TThread.Queue noch einen Parameter für die Ereignis-Methode angeben.

-Michael

Antworten