PostMessage -> Runerror(6)

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
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: PostMessage -> Runerror(6)

Beitrag von mschnell »

marcov hat geschrieben:Das ist auch eine art polling. Der centrale Event queue pollt nach messages. Genau wie select. Der einzige Unterschied ist das *nix nur auf file/socket descriptors kann Selecten(), und das der Mechanismus in Windows überall ist durchgeführt.
Nicht unbedingt. Ich weiß nicht, wie das in den einzelnen Plattformen implementiert ist, aber ein Lazarus-Programm erzeugt jedenfalls normalerweise nicht dauerhaft 100 % CPU-Zeit und die Latenz scheint auch ganz ordentlich zu sein. Wenn ich mich recht erinnere, verwendet MSE um z.B in Linux ohne GUI einen Timer-Events und "Procedure ..Message" Events zu realisieren einen Mutex zum Warten in der Main-Loop, der bei Auftreten irgendeines Events freigegeben wird. Also jedenfalls kein Polling. Ist eine GUI angebunden ist das natürlich komplizierter, weil die "Sprach-Events" (wie Timer-Events und "Procedure ..Message" Events) mit den GUI-Events gemischt werden müssen. Das macht in Lazarus daer Code des entsprechenden "Widget-Type"s.
marcov hat geschrieben:Ja das ist dumm. Was kann man nur mit ein paar 32-bit werte?
Wenn ich mich recht erinnere bietet MSE hier auch eine schönere Variante.
marcov hat geschrieben:Natürlich ?? Was ist natürlich daran Windows Systeme auf andere platform zu emulieren?
Das habe ich nicht gesagt. Ich meinte (1) Lazarus muss einen "FireMainThreadEvent" natürlich kompatiel für alle Platformen anbieten. (2) Wenn das identisch zu Delphi/Windows angeboten wird finde ich es nicht optimal (weil eben nur 4*32 Bit) aber auch nicht extrem störend.
marcov hat geschrieben:Lazarus hat schon ein System fuer die einfachsten 90%, und dass genügt. Ich denke auch das neue Software sich nicht darauf basieren soll. Reine Legacy und Porting-hilfe.
Lazarus hat aber eben keinen Cross-Plattform "FireMainThreadEvent" Event Mechanismus, der ohne den Thread anzuhalten im Mainthread ein Event auslösen kann, das nach Abarbeitung anderer MainThreadEvents ausgeführt wird. Weder ohne Parameter (wie ein asynchrones "Synchronize": wäre sehr schlecht), noch "anständig" mit einem ordentlichen Event-Typ-Paramter ()wie bei MSE). Oder habe ich es nur noch nicht gefunden ?
marcov hat geschrieben:Die Api wirt sehr slecht benutzt. Die meisten kontrolieren die Rueckgabe wert von Postmessage nicht. (was ernsthaft ist mit dynamische allocationen in die Message Parameter, Memory luecke)
Das mag durchaus sein. Thread Programmierung ist nur für "advanced Programmers" geeignet. Die sollten die Doku lesen können ;).
marcov hat geschrieben:Eine Windows emulation, genau so wie ich sachte.
Wie ich schon sagte, gibt es bessere Lösungen (Ich glaube z.B. richtige asynchrone Events bei MSE) aber solange keine andere in LCL implementiert ist, ist 4*32 Bit in jedem Fall besser als nichts.
marcov hat geschrieben:Aber der meist wichte Punkt, dass es mit TThread.Queue ein wirklich platform unabhaengige Loesung fuer dasselbe problem gibt, darauf hast du nicht kommentiert.
OK, Ich denke da nochmal d'rüber nach...
Ich fände aber "Procedure ...Event" mit einem ordentlichen Event-Type in Verbindung mit "FireMainThreadEvent() eine seht gut und intuitiv verwendbare Lösung (Die Grundidee dazu ist übrigens m.E. nicht aus Windows, sondern orientiert sich an Unix "signals".). (BTW.: Mein Lieblings-Thema: Wenn solche gequeuten "Thread-Events" nicht nur im Main Thread sondern auch in anderen Threads möglich wären (das geht übrigens in Delphi, wenn man im Thread ein TApplication instanziiert !) wäre es um so besser.

Gruß und Dank,
-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: PostMessage -> Runerror(6)

Beitrag von mschnell »

marcov hat geschrieben:Falsch. VCL/LCL ist Event gesteuert, nicht O. Pascal.
99 % aller Objet-Pascal Programme haben eine GUI-Bindung. Heute realisiert mit VCL, LCL oder bei Mac Objective Pascal mit der entsprechenden Library. TurboPascal (und FreePascal) kommt mit einer TUI, mit der ein man GUI-ähnliches Verhalten in einem nicht sofort beendenden Kommandozeilen-Programm mit einer "TUI" herstellen kann. Richtige "Comman-Line-Tools" die gestartet werden, ihr Ding tun und sich dann beenden, sind mit ObjectPascal natürlich möglich, aber inzwischen doch ziemlich selten.

Der einzige sinnvolle Weg auf von einer GUI erzeugte Ereignisse zu reagieren, ist. das Programm durchlaufen zu lassen und schlafen zu legen und einen oder mehrere "Handler" für von der GUI erzeugte Ereignisse vorzusehen. Ich bin ziemlich sicher, dass die Object Pascal Syntax mit Blick auf GUI und Event-Handler konzipiert wurde. Da aber es aber neben GUI-Ereignissen auch andere zum Mainthread eines Programms asynchrone Ereignisse gibt (z.B. von einem Worker-Thread oder auch von einem Timer erzeugte), ist es sicherlich sinnvoll für GUI-Ereignisse und andere asynchrone Ereignisse dasselbe Verfahren (also eine Ereignis-Warteschlange von der aus Ereignis-Handler getriggert werden) zu verwenden, unabhängig davon ob das Programm überhaupt eine GUI-Anbindung hat (z.B. für embedded "Server" Programme).

-Michael

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: PostMessage -> Runerror(6)

Beitrag von marcov »

mschnell hat geschrieben:
marcov hat geschrieben:Falsch. VCL/LCL ist Event gesteuert, nicht O. Pascal.
99 % aller Objet-Pascal Programme haben eine GUI-Bindung.
Ich zweifele sehr an diese Nummer. (zb Services, webapplication usw). Aber wichtiger, nutzen und Endwurfentscheidungen sind nicht unbedingt relatiert.
Object Pascal is nicht Event gesteuert, und nicht so entworfen. Egal für was sie genutzt wird.

Die VCL _ist_ ja event gesteuert und so entworfen. Aber das ist etwas anders als der Sprache.
Ich bin ziemlich sicher, dass die Object Pascal Syntax mit Blick auf GUI und Event-Handler konzipiert wurde.
Wirklich? Warum denn?
Da aber es aber neben GUI-Ereignissen auch andere zum Mainthread eines Programms asynchrone Ereignisse gibt (z.B. von einem Worker-Thread oder auch von einem Timer erzeugte),
Beide (Threads und Timers) sind meistens OS-, nicht Sprache Konzepten. Synchronize/checksynchronize ist eine Bibliothek Function, auch keine Sprache.

Starker eben, weil es in FPC/Delphi ein _bisschen_ Thread support in der Sprache (threadvars) gibt, sind Threads meistens auch kein Sprache Konzept (in (Object) Pascal allerdings). Es ist ein fast reine Bibliothek Implementation von ein OS Konzept. Und deshalb gibts kein Threads on zg FPC/Dos.
ist es sicherlich sinnvoll für GUI-Ereignisse und andere asynchrone Ereignisse dasselbe Verfahren (also eine Ereignis-Warteschlange von der aus Ereignis-Handler getriggert werden) zu verwenden,
Wenn das so ist, und absichtlich so gemeint ist, erkläre mich dann etwas. Warum ist der VCL nicht Threadsafe?

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: PostMessage -> Runerror(6)

Beitrag von Socke »

mschnell hat geschrieben:
Socke hat geschrieben:... Im Thread wird Synchronize(); mit einer Methode des Threads aufgerufen
Synchronize hält den Thread an, bis der Mainthread dazu kommt, das Event auszuführen.

Genau das soll vermieden werden, der Thread hat ja schließlich auch noch weiteres zu tun ! Deshalb wird ein komplett "asynchrones" Event gebraucht.

Der Threrad soll weiter laufen und dem Main Thread nur mitteilen, dass er irgendeinen Status erreicht hat (z.B. einfach, damit der Mainthread einen Scollbalken für den Fortschritt des Threads auf dem Form anzeigen kann.

-Michael
Okay, die andere Variante ist eine sind ein paar Variablen. Dazu gibt es soweit ich weiß sogar ein paar Funktionen, die das innerhalb weniger Assembler-Zeilen erledigen (System.Interlocked*; bspw. System.InterlockedExchange). Dann musst du aber wieder auf Polling durch den Mainthread (Main-Loop-Hook) zurückgreifen.
Mein Ansatz in meinem letzten Post war daher den Thread nur so kurz wie nötig anzuhalten und den Rest im Mainthread zu erledigen. Ich gehe davon aus, dass das ein Synchronisieren, das nur ein Application.QueueAsyncCall() aufruft nicht wirklich lange braucht (okay, Threadwechsel). Aber das eigentliche Abarbeiten der Message wird außerhalb des Synchronize() durchgeführt - und zwar asynchron (wenn man das so nennen darf) im Mainthread.

P.S.: Diskutiert ihr gerade darüber, ob Messages evil sind oder nicht? Ich glaub, das war nicht ganz so das Thema bzw. die Fragestellung. :P
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: PostMessage -> Runerror(6)

Beitrag von mschnell »

marcov hat geschrieben:Wenn das so ist, und absichtlich so gemeint ist, erkläre mich dann etwas. Warum ist der VCL nicht Threadsafe?
Der Sinn von Ereignis-gesteuertem programmieren ist ja gerade, Threads so weit wie möglich zu vermeiden um den Anwendungs-Programmierer vor der daraus sich ergebende Komplexität zu verschonen. Deshalb eben "run-to-completion"- Events, die nicht unerwartet unterbrochen werden können und sicher davor sind, dass eine andere Funktion auf die verwendeten Variablen zugreift.

Aus der "run-to-completion" Methodik folgt ziemlich zwingend die Verwendung von Objekten, weil hier der ganze komplexe Zustand zwischen zwei Aufrufen eines (oder mehrerer) run-to-completion Events festgehalten werden muss. Bei Thread-Programmierung passiert das automatisch, weil jeder Thread ja seinen eigenen Stack hat, auf dem alles lokale gespeichert bleibt auch wenn der Thread nicht rechenwillg ist oder verdrängt wird.

Daher im Endeffekt auch der von mir behauptete Zusammenhang zwischen GUI und objektorientierter Programmierung:
- GUI verlangt pseudo-parallele Verarbeitung.
- Das geht mit Threads oder mit run-to-completion Events.
- Threads machen die User-Programmieung unnötig kompliziert also run-to-completion Events.
- run-to-completion Events verlangen nach objekt-orientierter Programmierung:
Bingo.

-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: PostMessage -> Runerror(6)

Beitrag von mschnell »

Socke hat geschrieben:die andere Variante ist eine sind ein paar Variablen.
auf Variablen kann man nur pollen, die legen den Mainthread nicht schlafen. Also ganz böse: die CVPU-Zeit geht auf 100% und andere (z.B. GUI- oder Timer-) events werden nicht mehr ausgeführt.

-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: PostMessage -> Runerror(6)

Beitrag von mschnell »

mschnell hat geschrieben:
marcov hat geschrieben:Wenn das so ist, und absichtlich so gemeint ist, erkläre mich dann etwas. Warum ist der VCL nicht Threadsafe?
Der Sinn von Ereignis-gesteuertem programmieren ist ja gerade, Threads so weit wie möglich zu vermeiden um den Anwendungs-Programmierer vor der daraus sich ergebende Komplexität zu verschonen. Deshalb eben "run-to-completion"- Events, die nicht unerwartet unterbrochen werden können und sicher davor sind, dass eine andere Funktion auf die verwendeten Variablen zugreift.

Aus der "run-to-completion" Methodik folgt ziemlich zwingend die Verwendung von "Objekten" (am besten mit aber möglich auch oder ohne Unterstützung der verwendeten Sprache), weil hier der ganze komplexe Zustand zwischen zwei Aufrufen eines (oder mehrerer) run-to-completion Events festgehalten werden muss. Bei Thread-Programmierung passiert das automatisch, weil jeder Thread ja seinen eigenen Stack hat, auf dem alles lokale gespeichert bleibt auch wenn der Thread nicht rechenwillg ist oder verdrängt wird.

Daher im Endeffekt auch der von mir behauptete Zusammenhang zwischen GUI und objektorientierter Programmierung:
- GUI verlangt pseudo-parallele Verarbeitung.
- Das geht mit Threads oder mit run-to-completion Events.
- Threads machen die User-Programmieung unnötig kompliziert also run-to-completion Events.
- run-to-completion Events verlangen nach objekt-orientierter Programmierung:
Bingo.

-Michael

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: PostMessage -> Runerror(6)

Beitrag von marcov »

mschnell hat geschrieben:
Socke hat geschrieben:... Im Thread wird Synchronize(); mit einer Methode des Threads aufgerufen
Synchronize hält den Thread an, bis der Mainthread dazu kommt, das Event auszuführen.

Genau das soll vermieden werden, der Thread hat ja schließlich auch noch weiteres zu tun ! Deshalb wird ein komplett "asynchrones" Event gebraucht.

Der Threrad soll weiter laufen und dem Main Thread nur mitteilen, dass er irgendeinen Status erreicht hat (z.B. einfach, damit der Mainthread einen Scollbalken für den Fortschritt des Threads auf dem Form anzeigen kann.
Das ist was .Queue tut. Es nutzt wahrscheinlich denselben Warteschlange wie Synchronize, und nimmt auch ein Methode ohne Argumenten als einziges Argument. Den einzige unterschied ist das Synchronize() den calling Thread warten lässt, und Queue() nicht.

Es ist aber an Delphi seite D2006+, und in FPC noch nicht implementiert. (siehe eher erwähnte mantis Reporten)

Kernel
Beiträge: 35
Registriert: Di 13. Okt 2009, 14:10

Re: PostMessage -> Runerror(6)

Beitrag von Kernel »

Ich danke Euch auf jeden Fall für eure Beiträge/Diskussion.
Ich habe mittlerweise festgestellt, dass ein PostMessage in einem Synchronize erfolgreich ist. (d.h. ohne Programmabbruch).
Das hebelt m.E. den Sinn von PostMessage komplett aus.
Da ich meine GUI von den anderen Funktionen abkoppeln muss, bin ich auf eine asynchone Kommunikation angewiesen.

Mir ist im Moment nicht nicht ganz klar, ob das Verhalten ein Bug in der SVN-Version ist, oder ein nun anhaltender Zustand?!
Euerer Diskussion nach, scheint ja aber auch keine wirklich sinnvolle Alternative zu geben...

Gruß Kernel

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: PostMessage -> Runerror(6)

Beitrag von mschnell »

marcov hat geschrieben:Den einzige unterschied ist das Synchronize() den calling Thread warten lässt, und Queue() nicht.
Genau. Das ist aber ein Riesen-Unterschied. Wenn der Thread angehalten wird bis der Mainthread das Ereignis abgearbeitet hat ist die jede Latenz-Forderung hin. Der Mainthread könnte vorher noch hunderte ewig lang dauernde Ereignisse abarbeiten.
Außerdem ist heutzutage eine wichtige Aufgabe der Thread-Programmierung mehrere CPUs parallel zum Rechnen zu benutzen. Dazu verwendet man am besten Thread-Pools. Hier muss eine Fertigmeldung erfolgen und der Thread sofort wieder andere Aufgaben übernehmen.
[quote="marcov"Es ist aber an Delphi seite D2006+, und in FPC noch nicht implementiert. (siehe eher erwähnte mantis Reporten)[/quote] FPC bietet die Voraussetzng dafür indem die Mainthread-Seite durch Procedure ... Message als Sprach-Element implementiert ist. Die Worker Thread-Seite ist in Lazarus (bzw. MSE) in den "Wigget-Types" implementiert. (Wie gesagt, eine bessere Implementierung mit einem anständigen "Event" Type und einer anständigen "Event-Erzeuge" Methode in der RTL wäre mir auch lieber. Aber wie drehen uns im Kreis....)

-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: PostMessage -> Runerror(6)

Beitrag von mschnell »

Kernel hat geschrieben:Mir ist im Moment nicht nicht ganz klar, ob das Verhalten ein Bug in der SVN-Version ist, oder ein nun anhaltender Zustand?!
Euerer Diskussion nach, scheint ja aber auch keine wirklich sinnvolle Alternative zu geben...
Ich bin sehr sicher, dass es 'mal anständig funktioniert hat (in Windows und in KDE). Gibt es einen Bug-Report ?

-Michael

Kernel
Beiträge: 35
Registriert: Di 13. Okt 2009, 14:10

Re: PostMessage -> Runerror(6)

Beitrag von Kernel »

Gibt es einen Bug-Report ?
Jetzt schon...

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: PostMessage -> Runerror(6)

Beitrag von mse »

mschnell hat geschrieben: Die Worker Thread-Seite ist in Lazarus (bzw. MSE) in den "Wigget-Types" implementiert.
In MSEgui ist die main event queue in die MSEgui Version von TApplication implementiert. Eine entsprechende queue für threads gibt es in teventthread ebenfalls. "procedure...message" wird in MSEgui nicht verwendet sondern ievent:

Code: Alles auswählen

objecteventty = (oe_destroyed,oe_connect,oe_disconnect,
                  oe_changed,oe_designchanged,
                  oe_activate,oe_deactivate,oe_fired,oe_dataready);
 objectlinkeventty = procedure(const sender: tobject;
                    const event: objecteventty) of object;
 iobjectlink = interface(inullinterface)
  procedure link(const source,dest: iobjectlink; valuepo: pointer = nil;
                        ainterfacetype: pointer = nil; once: boolean = false);
  procedure unlink(const source,dest: iobjectlink; valuepo: pointer = nil);
               //source = 1 -> dest destroyed
  procedure objevent(const sender: iobjectlink; const event: objecteventty);
  function getinstance: tobject;
 end;
 
 tmseevent = class(tnullinterfacedobject)
  private
  protected
   fkind: eventkindty;
   procedure internalfree1; virtual;
  public
   constructor create(const akind: eventkindty);
   property kind: eventkindty read fkind;
   procedure free1; //do nothing for ownedevents
 end;
 
 tobjectevent = class(tmseevent,iobjectlink)
  private
   finterface: pointer; //ievent;
   procedure link(const source,dest: iobjectlink; valuepo: pointer = nil;
                 ainterfacetype: pointer = nil; once: boolean = false);
   procedure unlink(const source,dest: iobjectlink; valuepo: pointer = nil);
   procedure objevent(const sender: iobjectlink; const event: objecteventty);
   function getinstance: tobject;
  public
   constructor create(const akind: eventkindty; const dest: ievent);
   destructor destroy; override;
   procedure deliver;
 end;
 
 ievent = interface(iobjectlink)
  procedure receiveevent(const event: tobjectevent);
 end;
In der Regel wird in MSEgui Programmen nicht "synchronize()" sondern application.lock()/unlock() zur thread Synchronisation verwendet.

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: PostMessage -> Runerror(6)

Beitrag von mschnell »

Habe ich das richtig verstanden, dass es mit MSE möglich ist, dcem Main-Thrfead ein asynchrones Event zu schicken, das nicht nur (wir bei Delphi / Lazarus "Message") aus den "Windows-kompatiblen" 4 32-Bit Worten besteht, sondern eine richtige Event-Klasse darstellt.

Das müsste MarcoV doch viel besser gefallen, als das, was Lazarus anbietet.

Schade dass wir das in Lazarus nicht haben können :( (Ich hatte da ja schon 'mal was laufen, aber der Wartungs-Aufwand ist zu groß, wenn das parallel zu und unabhängig von der "Message" Implementierung existiert.)

"Synchronize" kann man mit application.lock und der Event-Queue sicher sehr leicht bastlen.

-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: PostMessage -> Runerror(6)

Beitrag von mse »

mschnell hat geschrieben:Habe ich das richtig verstanden, dass es mit MSE möglich ist, dcem Main-Thrfead ein asynchrones Event zu schicken, das nicht nur (wir bei Delphi / Lazarus "Message") aus den "Windows-kompatiblen" 4 32-Bit Worten besteht, sondern eine richtige Event-Klasse darstellt.
Ja. Auch an teventthread.
"Synchronize" kann man mit application.lock und der Event-Queue sicher sehr leicht bastlen.
Synchronize gibt es auch in MSEgui, es wird nur selten verwendet.

Antworten