Ersatz für Application.ProcessMessages()

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Ersatz für Application.ProcessMessages()

Beitrag von Targion »

Hallo!
Ich habe eine Bibliothek geschrieben, welche auf Signale einer System-Daemons unter Linux wartet.
Das Ganze hat folgenden Stil:

Code: Alles auswählen

aktion_starten;
  while not aktion_beendet do Application.ProcessMessages;
Allerdings kann ich das ProcessMessages des Application-Objektes nicht benutzen, da es in der Unit "Forms" enthalten ist und in der Lib wirkungslos ist. Wenn ich allerdings

Code: Alles auswählen

while not aktion_beendet do begin end;
benutze, kommt das Signal nicht an, es wird eine Variable nicht gesetzt, welche die Aktion als beendet markiert und das Programm hängt sich in einer Endlosschleife auf.
Gibt es ein NonVCL ProcessMessage, welches die Anwendung onder Lib auf Events reagieren lässt?

(Post in Delphipraxis, damit habe ich leider nur ein Windowslösung)

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: Ersatz für Application.ProcessMessages()

Beitrag von Socke »

Woher hast du denn deine Message-Queue, wenn du kein Appplication-Objekt hast?

Ansonsten wirf mal einen Blick auf TCustomApplication
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

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: Ersatz für Application.ProcessMessages()

Beitrag von mse »

Targion hat geschrieben: Allerdings kann ich das ProcessMessages des Application-Objektes nicht benutzen, da es in der Unit "Forms" enthalten ist und in der Lib wirkungslos ist.
Übertrage die TApplication Instanz des Hauptprogrammes mittels init-routine oder so in die Bibliothek, ruf einen callback auf oder benütze threads.

Martin

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Ersatz für Application.ProcessMessages()

Beitrag von Targion »

mse hat geschrieben:
Targion hat geschrieben: Allerdings kann ich das ProcessMessages des Application-Objektes nicht benutzen, da es in der Unit "Forms" enthalten ist und in der Lib wirkungslos ist.
Übertrage die TApplication Instanz des Hauptprogrammes mittels init-routine oder so in die Bibliothek, ruf einen callback auf oder benütze threads.
Martin
Da hätte ich eine Lösung... Kommt mir aber ziemlich dämlich vor, einen OnIdle-Callback benötigen zu müssen.

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: Ersatz für Application.ProcessMessages()

Beitrag von mse »

Targion hat geschrieben: Da hätte ich eine Lösung... Kommt mir aber ziemlich dämlich vor, einen OnIdle-Callback benötigen zu müssen.
Dann die Version mit der importierten Hauptprogramm TApplication Instanz? Wie Socke bereits geschrieben hat, wenn du messages aus dem Hauptprogramm beziehst, muss die Bibliothek ja Zugriff auf Hauptprogramm.Application haben?
Ein OnIdle-Callback dünkt mich nicht so verkehrt, da du ja nicht wissen kannst, was die Anwender mit deiner Bibliothek alles anstellen wollen...

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: Ersatz für Application.ProcessMessages()

Beitrag von mschnell »

IMHO ist das ganze keine gute Idee.

In Linux wird die Kommunikation zwischen unterschiedlichen Software-Instanzen (Programm und Netzwerk, Programm und Treiber oder Programm und Daemon) am besten über virtuelle Dateien geregelt. Dafür bietet das System alle Building-Blocks.

Unbedingtes Warten geht z.B. mit einem normalen (blocking) read(). Will das Programm auf mehrere Sachen gleichzeitig warten, gibt es z.B. select() oder epoll().
Zwischen zwei Programmen (oder eben einem Programm und einem Daemon) kann man dafür mit mkfifo eine Pipe (virtuelle Datei) irgendwo im Filesystem einrichten.

Die "Message Queue" in Lazarus (die z.B. mit "Application.ProcessMessages" behandelt wird) wird mit Hilfe des Windowing-Systems (QT) aufgebaut und ist nur für GUI-Operationen wirklich gut.

Ich würde also vorschlagen, Du machst einen Thread, der über eine virtuelle Datei mit dem Deamon kommuniziert. Dann kannst Du die normalen Lazarus/FPC Thread-Synchronisations-Mechanismen (schlecht: TThread.Synchonize, besser: z.B. TThreadList und SyncOBJs) zur Kommunikation mit der GIU verwenden (falls das Programm überhaupt eine GUI haben soll),

-Michael

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Ersatz für Application.ProcessMessages()

Beitrag von Targion »

Ich weiß nicht, ob ich so eine aufwändige Lösung wirklich brauche.
Das Daemon-Problem habe ich anderweitig gelöst, jetzt geht es darum, dass ich mit

Code: Alles auswählen

g_signal_connect()
ein Signal einer in C geschriebenen Lib auf eine eigene Prozedur umleite. Dummerweise empfängt meine Anwendung dieses Signal ja nicht, um die Schleife zu verlassen.
Gibt es eine Art "ProcessSignals()" funktion, um auf solche externen Signale reagieren zu können?

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

Re: Ersatz für Application.ProcessMessages()

Beitrag von theo »

Bin nicht ganz sicher, ob sich das mit deinem Problem vereinen lässt, aber wenn du die lshalpas.pp demo anschaust, dort wird sich auch in einen "g_main_Loop" eingehängt um die Ereignisse mitzubekommen.

Also etwa:
g_main_loop_new(nil, FALSE);
Dann werden über Umwege die Ereignisse eingehängt:
z.B. libhal_ctx_set_device_added(hal_ctx, @device_added);
g_main_loop_run(loop);

Nur ne Vermutung, frag mich nicht. ;-)

Bei einer GTK2 Anwendung kann man sich den loop Krempel sparen, dort reicht glaub's in meinem Beispiel:
dbus_connection_setup_with_g_main(conn, nil);

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Ersatz für Application.ProcessMessages()

Beitrag von Targion »

Die Anwendung, um die es geht (mal wieder der Listaller ;-)) sollte möglichst nur von der GLib abhängen.
Hier mal die Unit um die es geht: (im Versionskontrollsystem) (macht vielleicht einiges einfacher)
Ob die Implementierung von PackageKit jetzt so glücklich ist, ist noch egal. Ich musste das alte TPackageKit-Objekt erstmal erhalten, um nicht jede Unit komplett neu schreiben zu dürfen.
Wie genau funktioniert das mit dem Loop?

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

Re: Ersatz für Application.ProcessMessages()

Beitrag von theo »

Targion hat geschrieben: Wie genau funktioniert das mit dem Loop?
Wie gesagt, genau weiss ich das auch nicht. Ich vermute nur, dass wenn du selber in eine Warteschleife gehst, statt
g_main_loop_run(loop);
aufzurufen, dass du dann die G-Signale nicht mitkriegst.

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Ersatz für Application.ProcessMessages()

Beitrag von Targion »

Nein, ich meine ob ich meine Signale da irgendwie mit dem Loop verbinden muss...
Ich probier's einfach mal ohne... Danke schonmal für den Tipp!

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

Re: Ersatz für Application.ProcessMessages()

Beitrag von theo »

Naja, das musst du nat. selber nachschauen.
Ich weiss nur, dass ein simplizistischer MainLoop auf Windows pseudo-mässig etwa so aussieht:

while true do begin
GetMessage
TranslateMessage
DispatchMessage
end;

Wird bei deinem Problem vllt. ähnlich sein. Vllt fasst g_main_loop_run(loop) das nötige auch zusammen und schmeisst dann die eingehängten signals. In die Message Queue wirst du dich wohl irgendwie einhängen müssen.

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: Ersatz für Application.ProcessMessages()

Beitrag von mschnell »

Targion hat geschrieben:Ich weiß nicht, ob ich so eine aufwändige Lösung wirklich brauche.
Das Problem ist alles andere als simpel, weil Du die grundsätzliche Arbeitsweise der RTL (Message Queue) umgehen, erweitern oder beeinflussen willst.

Die einzige sinnvolle Methode das zu tun (wenn Du nicht komplett auf die Message Queue verzichten willst (also kein GUI-"Anwendung", sondern ein "Command Line Programm" machen willst) ), ist es, eine Message in der Message Queue zu erzeugen, um das anfallende Ereignis zu bearbeiten. Warten auf ein Ereignis, das nicht "von selber" in der Message Queue auftaucht, kannst Du nur in einem Thread, weil der Mainthread grundsätzlich nicht warten kann, sonst wäre die Anwendung komplett blockiert.

-Michael

martin_frb
Beiträge: 588
Registriert: Mi 25. Mär 2009, 21:12
OS, Lazarus, FPC: Laz trunk / fpc latest release / Win and other
CPU-Target: mostly 32 bit

Re: Ersatz für Application.ProcessMessages()

Beitrag von martin_frb »

Also wenn es nur darum geht das der Code regelmäßig aufgerufen wird während die Main-Loop normal läuft:
Application.QueueAsyncCall
Application.AddOnIdleHandler

QueueAsyncCall hat den Vorteil es wird auch aufgerufen wenn die Application nicht Idle ist. Jedes mal wenn der Code von QueueAsyncCall aufgerufen wurde, muss er sich selber neu in QueueAsyncCall eintragen (Das ist ein einmal Aufruf)

Targion
Beiträge: 688
Registriert: Mi 3. Okt 2007, 21:00
OS, Lazarus, FPC: Linux (L 0.9.29 FPC 2.4.2)
CPU-Target: x86_64

Re: Ersatz für Application.ProcessMessages()

Beitrag von Targion »

Ich muss das ganze Objekt wohl in einen extra-Thread packen und hoffen, dass die GLib-Signale dann empfangen werden.
Allerdings gibt es da ein Problem: Wie lautet denn der Befehl, um GLib-Signale direkt zu verarbeiten? Bis jetzt habe ich da nichts finden können.
Shonmal Danke für die Hilfe! Vielleiht finde ich ja doch noch einen passenden Befehl auf library.gnome.org

Antworten