Ersatz für Application.ProcessMessages()

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 muss das ganze Objekt wohl in einen extra-Thread packen

Also, "Objekt" ist Variablen- und Code-Verwaltung, Thread ist Ablaufsteuerung. Das hat eigentlich wenig mit einander zu tun. Ein Objekt kann mehrere Threads verwalten und ein Thread kann auf Daten und Code mehrerer Objekte zugreifen. Dasselbe Unterprogramm (Memberfunktion eines Objektes) kann natürlich auch vom Mainthread und verschiedenen Threads aufgerufen werden. Ein Objekt kann im Mainthread instanziiert werden und ansonsten nur in Worker-Threads benutzt werden (oder auch umgekehrt). Von TThread abgeleitete Objekte haben Memberfunktionen, die normalerweise nur im Mainthred ablaufen werden (.Synchronize), ...

-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 »

Das stimmt schon... Blöderweise gibt es nichts, was ich geziehlt parallel laufen lassen könnte... Die Signale machen was sie wollen... Es muss einen Befehl geben, der einen Thread (die Anwendung) zwingt sofort auf alle Signale der GLib zu hören. Den muss ich aber erst mal finden.

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:Die Signale machen was sie wollen... Es muss einen Befehl geben, der einen Thread (die Anwendung) zwingt sofort auf alle Signale der GLib zu hören. Den muss ich aber erst mal finden.
Meinst Du mit "Signale der GLib" tatsächlich Linux "Signals" ("kill" und so) ?

Um so eines zu behandeln, braucht der Prozess einen Signalhandler. Den kann man mit einem System Call anmelden. Er läuft dann, sobald das Signal auftritt - ähnlich wie ein Thread - anstelle des Mainthread und kann auf die Variablen des Programms zugreifen ("Signale und Threads" ist wieder irgendwas spezielles)

Ich weiß nicht, ob es in der RTL eine Abstaktion für "Signals" gibt.

Es sollte möglich sein, mit Syncobjs von einem Signal-Handler aus eine Message an den Mainthread zu schicken, die dann an in der Mainthread-Message-Loop verarbeitet wird.

-Michael

Socke
Lazarusforum e. V.
Beiträge: 3158
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 »

Targion hat geschrieben: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

GLib Signale (der GObjects) sind auch nur Callbacks. Verbinden geht mit g_signal_connect() bzw. einer Variante von g_signal_connect_<name>().
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

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 »

Genau. Und diese dürfen auch nicht an ein Objekt gebunden sein, sondern sind als freie Prozeduren im Quellcode.
Gibt es vielleicht allgemein ein Kommando, um das verarbeiten von Callbacks zu erzwingen?

Socke
Lazarusforum e. V.
Beiträge: 3158
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 »

Targion hat geschrieben:Genau. Und diese dürfen auch nicht an ein Objekt gebunden sein, sondern sind als freie Prozeduren im Quellcode.
Gibt es vielleicht allgemein ein Kommando, um das verarbeiten von Callbacks zu erzwingen?

Ich weiß zwar nicht, was du mit "erzwingen" meinst, aber ich denke, es gibt schon eine Möglichkeit Methoden in den Callbacks zu verwenden.
Voraussetzung ist, dass die Callback-Funktion als ersten Parameter einen Zeiger besitzt und ein weiterer, benutzerdefinierter Zeiger übergeben wird (üblicherweise user_data).
Als Funktionszeiger muss dann

Code: Alles auswählen

TMethod(@myobj.Proc).code
verwendet werden. Der benutzerdefinierte Zeiger muss ein Zeiger auf die Instanz, die den Callback verarbeiten soll enthalten (wir beim Registrieren des Callbacks festgelegt).
Bei den Parametern nutzen wir dann die Tatsache, dass jede Methode den impliziten (nicht aufgeführten) Parameter "Self: TMyClass" besitzen. In der Deklaration werden dann nur noch alle anderen Parameter außer dem ersten Zeiger angegeben.

Code: Alles auswählen

procedure TMyClass.Callback(alle außer dem ersten Parameter; user_data: gpointer); cdecl;
var
  erster_parameter: TGObject; // oder gpointer
begin
  erster_parameter := TGObject(Self);
  Self := TMyClass(user_data);
  // jetzt kann man so wie sonst auch arbeiten
end;

Diese Zuweisungen dienen nur der Bequemlichkeit. Wenn man sie nicht macht, muss man bei jedem Zugriff auf ein Element des Objektes TMyObject(user_data).<Bezeichner> benutzen, da nur <Bezeichner> wirklich nur im besten Fall eine Zugriffsverletzung erzeugen.

Soweit meine Theorie (getestet habe ich das aber noch nicht). Alternativ dürfte das gtk2-Interface der LCL ein paar Beispiele geben.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

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 »

Funktioniert... Hilft aber auch nicht. Ich der g_main_loop-Ansatz ist schon recht gut, aber irgendwie bekomme ich da nichts brauchbares raus...

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 »

Socke hat geschrieben:
Targion hat geschrieben: Self := TMyClass(user_data);

Ooops ?!?!?! Den Self-Pointer darf man ändern ????

Danach kommt man an die ursprüngliche Instanz nicht mehr ran. Free geht vermutlich schief....

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

Beitrag von mschnell »

Targion hat geschrieben:Funktioniert... Hilft aber auch nicht. Ich der g_main_loop-Ansatz ist schon recht gut, aber irgendwie bekomme ich da nichts brauchbares raus...
Wenn Du in der GUI was sehen willst, musst Du - wie gesagt - vermutlich eine (QT-) Message schicken.

-Michael

Socke
Lazarusforum e. V.
Beiträge: 3158
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 »

mschnell hat geschrieben:
Socke hat geschrieben:
Targion hat geschrieben: Self := TMyClass(user_data);

Ooops ?!?!?! Den Self-Pointer darf man ändern ????

Danach kommt man an die ursprüngliche Instanz nicht mehr ran. Free geht vermutlich schief....

-Michael

Wenn du meinen Post ganz gelesen hättest, wüsstest du, dass Self in diesem Fall nicht auf ein Objekt der Klasse TMyClass zeigt sondern den Inhalt des ersten Parameters des Callbacks enthält. Deshalb muss ein Zeiger auf das Objekt anderweitig übergeben werden.

Wenn Self aber eine Referenz ist, würde man tatsächlich den Zugriff auf dieses Objekt einschränken. Aber da man es ja auf den selben Wert ändert, dürfte Free immer noch funktionieren (außerdem sollte sich ein Objekt nie selbst freigeben).

Um das Ursprüngliche Problem lösen zu können, wäre es vielleicht hilfreich, nochmal die konkrete Situation darzustellen, da ich gerade gar nicht weiß, was los ist und wo es hin gehen soll (was erreicht werden soll).
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

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 »

Wie schon gesagt, hier nochmal das konkrete Problem:
Ladet euch die PackageKit-Unit hier aus der Versionskontrolle herunter. Die Unit hat in dieser etwas älteren Revision (die neue behebt einige fiese Bugs in der Unit, die aber nichts mit dem Problem zu tun haben) keine Abhängigkeiten zu Listaller Modulen, sollte also problemlos kompilieren.
=> Neues Testprojekt, packagekit-Unit einbinden
Dann:

Code: Alles auswählen

var pkit: TPackageKit;h: TStringList;
begin
  pkit:=TPackageKit.Create;
  h:=TStringList.Create;
  pkit.RsList:=h;
  pkit.FindPkgForFile('/usr/bin/amor');
  while (not pkit.PkFinished) do
  begin
    //Application.ProcessMessages;
  end;
  ShowMessage(IntToStr(pkit.PkFinishCode));

An der auskommentierten Stelle müsste Code rein, der das GLib-Signal-Handling ermöglicht.

Socke
Lazarusforum e. V.
Beiträge: 3158
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 »

Targion hat geschrieben:Wie schon gesagt, hier nochmal das konkrete Problem:
Ladet euch die PackageKit-Unit hier aus der Versionskontrolle herunter. Die Unit hat in dieser etwas älteren Revision (die neue behebt einige fiese Bugs in der Unit, die aber nichts mit dem Problem zu tun haben) keine Abhängigkeiten zu Listaller Modulen, sollte also problemlos kompilieren.
=> Neues Testprojekt, packagekit-Unit einbinden
Dann:

Code: Alles auswählen

var pkit: TPackageKit;h: TStringList;
begin
  pkit:=TPackageKit.Create;
  h:=TStringList.Create;
  pkit.RsList:=h;
  pkit.FindPkgForFile('/usr/bin/amor');
  while (not pkit.PkFinished) do
  begin
    //Application.ProcessMessages;
  end;
  ShowMessage(IntToStr(pkit.PkFinishCode));

An der auskommentierten Stelle müsste Code rein, der das GLib-Signal-Handling ermöglicht.

Ich habe gerade ein wenig in der LCL nachgeschaut, siehe <lazarus>/lcl/interfaces/gtk2/gtk2callback.inc, und dort wird es anscheinend auch nur über einfache Prozeduren/Funktionen erledigt. Als user_data wird dann das entsprechende LCL-Control übergeben. Somit hast du auch Zugriff auf dein Ojekt und kannst dort dann bspw. eine Variable setzen, die bewirkt, dass die Schleife beim nächsten Durchlauf verlassen wird.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

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 Schleife soll aber verlassen werden, wenn das PackageKit-Signal eine Variable setzt :)
Oder habe ich was in dem Code übersehen? Ich kann keine Stelle mit Event-Handling finden.

Antworten