Methode im ThreadContext ausführen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: Methode im ThreadContext ausführen

Beitrag von theo »

Bergmann89 hat geschrieben: es wird sicher keine echte EventQueue, ich leite einfach ne Klasse von TThread ab, der eine mit CriticalSections geschützte Queue hat. Dann schreib ich eine Mehtode, mit der andere Threads eine Art Message bei dem Thread abgeben können. Im Execute des Threads arbeite ich dann die Liste ab. Macht genau das was ich will und lässt sich relativ einfach implementieren...
Du machst das schon richtig Bergmann89. Lass dich nicht beirren.
mschnell schwafelt gerne viel Käse und beschwört Probleme, die sonst keiner hat. :wink:

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: Methode im ThreadContext ausführen

Beitrag von mschnell »

Bergmann89 hat geschrieben:es wird sicher keine echte EventQueue, ich leite einfach ne Klasse von TThread ab, der eine mit CriticalSections geschützte Queue hat. Dann schreib ich eine Mehtode, mit der andere Threads eine Art Message bei dem Thread abgeben können. Im Execute des Threads arbeite ich dann die Liste ab
Eine einfache Queue kannst Du natürlich mit Threadlist machen. Das ist dafür vorgesehen und deshalb ist da automatisch eine Critical Section drin (um die konkurrierenden Zugriffe auf die Queue zu schützen, nicht um das Warten eines Threads auf ein Ereignis zu realisieren. Du brauchst beides).

Die Frage ist nun wie ein Thread, der gerade nichts zu tun hat, darauf wartet, dass er ein Aufgabe bekommt, ohne dass er CPU-Zeit verbrät und die anderen Threads dadurch hemmt. Wenn Du das ganze nicht machst, um eine Beschleunigung des Projektes durch Multi-Processing zu erreichen (dann wäre auch TThreadlist ein Klotz am Bein -> siehe "Lockfree FiFo"), gibt es da eine ganze Menge einfacher Möglichkeiten. Es geht vermutlich mit einer Critical Section (nicht sehr schön) oder TEvent (schöner) Auch "Suspend" sollte möglich sein (wie ich finde: ganz hässlich). Theoretisch kannst Du auch die Threads immer sterben lassen und neu kreieren. Das ist aber in jedem Fall die langsamste Methode. (Deshalb verwenden z.B. Webserver meist einen "Threadpool". Sowas ist in "Indy" implementiert).

-Michael
Zuletzt geändert von mschnell am Mi 17. Okt 2012, 19:02, insgesamt 1-mal geändert.

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: Methode im ThreadContext ausführen

Beitrag von mschnell »

theo hat geschrieben:mschnell schwafelt gerne viel Käse und beschwört Probleme, die sonst keiner hat. :wink:
Danke Theo, der Meister der unzulässigen Vereinfachung, der trotzdem - oder gerade deshalb - oft gute Ideen hat .

-Michael
Zuletzt geändert von mschnell am Do 18. Okt 2012, 09:12, insgesamt 1-mal geändert.

Bergmann89
Beiträge: 98
Registriert: Di 15. Nov 2011, 11:36

Re: Methode im ThreadContext ausführen

Beitrag von Bergmann89 »

Das Problem mit der CPU-Last hab ich zur Zeit mit nem sleep(1) gelöst, das wollt ich später noch besser machen. Bis jetzt reicht das aber. CPU-Last is bei 0, wenn er nix macht. Und wenn er Daten vom Netzwerk bekommt oder Nachrichten in der Queue hat, wird das sleep einfach übersprungen, bis alles abgearbeitet ist.

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: Methode im ThreadContext ausführen

Beitrag von mschnell »

Bergmann89 hat geschrieben:das wollt ich später noch besser machen
Gut !

Mit sleep(1) gibt der Thread eigentlich nur die aktuelle Zeitscheibe auf. Sobald die nächste Zeitscheibe dran kommt, läuft er wieder eine Runde in der Schleife und verbrät somit unnötig CPU-Zeit, die ansonsten anderen Threads und Prozessen zur Verfügung stehen würde. Außerdem reagiert er auf eine Anforderung nicht sofort, sondern erst wenn er mit der nächsten Zeitscheibe das sleep verlässt (Latenz).

Durch vergrößern er Wartezeit verringerst Du die vergeudete CPU-Zeit und erhöhst dafür die Latenz .

Besser ist ein Warte-Mechanismus, der durch einen anderen Thread beendet werden kann (dann, wenn er einen Auftrag in die Queue geschrieben hat). Ich glaube TEvent.Waitfor und TEvent.SetEvent oder so ähnlich machen das Plattform-unabhängig. Hier wird der Prozess (soweit ich weiß) sofort rechenwillig, ohne auf die nächste Zeitscheibe zu warten. (Habe ich aber noch nicht getestet).

-Michael

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Methode im ThreadContext ausführen

Beitrag von mse »

Bergmann89 hat geschrieben:Ich werd jetzt schnell selbst was schreiben. Meine Consolenanwendung und LCL vertragen sich nicht, da schmiert jedesmal der Linker ab, wenn ich LCL in die Abhangigkeiten mit rein nehm. Eigentlich hat die LCL ja auch nix in Consolenanwendungen zu suchen...
Ehem, du hast aber schon gelesen, dass MSEgui einen ereignisgesteuerten Konsolenmodus ohne GUI-Anbindung bereitstellt? Die entsprechenden MSEgui units lassen sich sicher auch in Lazarus kompilieren, falls MSEide nicht das richtige für dich ist.
Einige Beispiele mit MSEide Projekt sind hier:
https://gitorious.org/mseuniverse/mseun ... ials/nogui

Martin

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: Methode im ThreadContext ausführen

Beitrag von mschnell »

Bergmann89 hat geschrieben:Eigentlich hat die LCL ja auch nix in Consolenanwendungen zu suchen...
Hmm. Dafür kann man in Lazarus in den Projekt-Optionen verschiedene "Widget-Types" aussuchen, die den Build-Prozess dann so beeinflussen, dass die passenden / passend konfigurierten Teile der LCL verwendet werden.

Obwohl "Widget" natürlich nach GUI klingt, gibt es hier durchaus auch Auswahlmöglichkeiten, die keine GUI anbinden. (Wie gesagt bieten diese leider alle keine Event-Queue, erlauben also kein Event-orientiertes Programmieren und Sachen wie TTimer).

-Michael

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: Methode im ThreadContext ausführen

Beitrag von mschnell »

mse hat geschrieben: Die entsprechenden MSEgui units lassen sich sicher auch in Lazarus kompilieren, falls MSEide nicht das richtige für dich ist.
Dann mach doch 'mal einen Lazarus "Widget-Type" "EventDrivenNonGUI" daraus, damit wir das endlich problemlos einsetzen können. Die wichtigen Funktionen wie TTimer, QueueAsyncCall(), TThread.Synchronize(), PostMessage() und "procedure ... message" müssten natürlich funktionieren. :evil:

(Im Gegensatz zu mir wird Dich dabei sicher nicht stören, dass die in der LCL schon vorhandenen Implementierungen einer Event Queue nicht benutzt werden sondern Deine dadurch zusätzlich aufgenommene Implementierung erforderlich ist. :lol: )

-Michael

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Methode im ThreadContext ausführen

Beitrag von mse »

mschnell hat geschrieben:
mse hat geschrieben: Die entsprechenden MSEgui units lassen sich sicher auch in Lazarus kompilieren, falls MSEide nicht das richtige für dich ist.
Dann mach doch 'mal einen Lazarus "Widget-Type" "EventDrivenNonGUI" daraus, damit wir das endlich problemlos einsetzen können.
Hast du das nicht bereits gemacht? Soviel ich weiss habe ich für dich sogar Änderungen in MSEgui durchgeführt um deine Arbeit zu erleichtern.

Martin

Bergmann89
Beiträge: 98
Registriert: Di 15. Nov 2011, 11:36

Re: Methode im ThreadContext ausführen

Beitrag von Bergmann89 »

Hey,
mschnell hat geschrieben:Besser ist ein Warte-Mechanismus, der durch einen anderen Thread beendet werden kann (dann, wenn er einen Auftrag in die Queue geschrieben hat). Ich glaube TEvent.Waitfor und TEvent.SetEvent oder so ähnlich machen das Plattform-unabhängig. Hier wird der Prozess (soweit ich weiß) sofort rechenwillig, ohne auf die nächste Zeitscheibe zu warten. (Habe ich aber noch nicht getestet).
Ich hab schonma versucht das ganze Event gesteuert zu machen, hab das dann aber aufgegeben, als ich festgestellt hab, das die Sockets keine Events werfen, wenn neue Daten da sind. Das muss immer explizit abgefragt werden. Zumindest hab ich das grad noch so im Kofp. Müsst ich nochma nachgucken wie das genau war...

MfG Bergmann

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: Methode im ThreadContext ausführen

Beitrag von mschnell »

mse hat geschrieben:Hast du das nicht bereits gemacht? Soviel ich weiss habe ich für dich sogar Änderungen in MSEgui durchgeführt um deine Arbeit zu erleichtern.
Schön wärs. :(

Du hast einen Typ umbenannt, sonst wäre es gar nicht möglich. Ich hatte aber damals vor, zu vermeiden, jede Menge neuen Code in die LCL einzubringen, der die Queue-Funktionalität reproduziert, die in anderen Widgets ja schon implementiert ist. Ich habe im Forum vorgeschlagen, diese Funktionalität für alle Widget-Typen zentral (außerhalb des Directories für den einzelnen Widget-Typ) zu halten. Es wollte sich aber keiner drauf einlassen die vorhandenen Implementierungen zu überarbeiten. Im Laufe dieser Diskussion ist meine Motivation geschrumpft, weil das Projekt in unserer Firma, für das ich es gebraucht hätte, für unbestimmte Zeit auf Eis gelegt worden ist.

Inzwischen ist es ohnehin nicht mehr so wichtig, weil ja sehr preiswerte embedded ARM-Hardware mit schnellem Prozessor und viel RAM verfügbar ist, so dass die Vermeidung der GUI nicht mehr viel Sinn macht (auch wenn sie nie jemand sehen wird).

Gruß,
-Michael

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: Methode im ThreadContext ausführen

Beitrag von mschnell »

Bergmann89 hat geschrieben:hab das dann aber aufgegeben, als ich festgestellt hab, das die Sockets keine Events werfen, wenn neue Daten da sind. Das muss immer explizit abgefragt werden.
Natürlich "werfen sie keine Events". Das mit den Events ist ja eine Sache der Programmier-Sprache und nicht der Betriebssystem-API.

Aber genau dafür machst Du ja die Threads ! Jeder Socket bekommt einen Thread und der macht einen Blocking Read auf den Socket. Damit steht der Thread still und verbrät keine CPU-Zeit. Wenn Daten ankommen, wird der Thread vom Betriebssystem automatisch gestartet und das read durchgeführt. Der Thread kann dann (wi vorher besprochen über einen Eintrag in die Queue (TThreadlist) und setzen des Events einen wartenden anderen (z.B. einen zentralen, für alle Sockets gemeinsamen) Thread aktivieren, der dann die angekommenen Daten verteilt oder sonstwas tut.

-Michael

Bergmann89
Beiträge: 98
Registriert: Di 15. Nov 2011, 11:36

Re: Methode im ThreadContext ausführen

Beitrag von Bergmann89 »

Hey,

wir nutzen die lNet Sockets, da is das alles bisl anders. Wie genau der dann die normalen Windows- bzw. Linux-Sockets anspricht weiß ich nicht. In nem anderen Thread hatten wir auch schonma diskutiert, dass das iwie nich wirklich eventbasiert geht. Zumindest nich, wenn ich es auf Linux und Windoof nutzen will.

MfG Bergmann.

Benutzeravatar
theo
Beiträge: 10872
Registriert: Mo 11. Sep 2006, 19:01

Re: Methode im ThreadContext ausführen

Beitrag von theo »

Bergmann89 hat geschrieben: wir nutzen die lNet Sockets,
Wäre für sowas Synapse nicht der "natürlichere Weg"?

Bergmann89
Beiträge: 98
Registriert: Di 15. Nov 2011, 11:36

Re: Methode im ThreadContext ausführen

Beitrag von Bergmann89 »

Ich hab mir mehrere Sachen angesehen, und da hat mir lNet halt am bessten gefallen^^ Bis jetzt laufen die auch super. Bis auf das mit den Events, aber ich find ein sleep(1) da nich so tragisch. Vorher lief der Thread auf Volllast :mrgreen:

Antworten