Alternative für Application.ProcessMessages in Lib["gelöst"]

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Alternative für Application.ProcessMessages in Lib["gelöst"]

Beitrag von RSE »

In der Library steht ja leider die Variable ProcessMessages nicht zur Verfügung. Gibt es eine Alternative für Application.ProcessMessages? Also quasi ein Befehl für "mach erstmal alles, was sonst ansteht, bevor du an dieser Stelle weitermachst".

Beschreibung des konkreten Hintergrundes: Wie schon im Thread Kaskade von Librarys wird nicht richtig freigegeben habe ich eine Application, die das Userinterface meines Mediaplayers beinhaltet. Diese lädt eine Library mit dem Kern des Mediaplayers. Diese Library lädt eine weitere Library mit der DirectShow-Anbindung (Medienwiedergabeframework von Windows). Wenn meine MainForm geschlossen wird, terminiert die Application. Im OnFormDestroy wird die Library mit dem Mediaplayer unloaded. Im Finalization-Abschnitt einer Unit dieser Library wird das Mediaplayer-Objekt freigegeben. In der Destroy-Routine des Mediaplayers wird die Library mit der DirectShow-Anbindung unloaded. Im Finalization-Abschnitt einer Unit der DirectShow-Library wird das DirectShow-Hauptobjekt freigegeben. In der Destroy-Routine des DirectShow-Objektes wird eine eventuell laufende Wiedergabe gestoppt und anschließend alle COM-Interfaces auf DirectShow auf nil gesetzt. Im Finalization-Abschnitt einer weiteren DirectShow-Unit wird CoUninitialize aufgerufen, was die Kommunikation mit DirectShow aus Windows-Sicht beendet. Der Finalization-Abschnitt mit CoUninitialize wird nach der Freigabe des DirectShow-Objektes ausgeführt, da bin ich mir sicher.

Problem: Wird ein Song wiedergegeben, dann sehe ich das an einem Tasktray-Symbol von FFDShow, einem DirectShow-Filter. Wird die Wiedergabe durch oben genannte Prozedur beendet, dann bleibt dieses Icon bestehen und der Player stürzt ab. Wird die Wiedergabe vorher beendet, ist das Icon damit verschwunden und der Player kann fehlerfrei beendet werden. Ich vermute, dass nach dem nil-Setzen der COM-Interfaces ein Application.ProcessMessages benötigt wird, um die referenzgezählten Interfaces tatsächlich freizugeben, bevor die Application beendet wird. Oder es stehen noch Windows-Messages zur Behandlung an, die bearbeitet werden müssen, bevor alles freigegeben wird.

Edit: Ich habe mir mit Windows-API-Aufrufen in der DirectShow-Library ein Window besorgt, um an Ort und Stelle über eine entsprechende WndProc (die direkt von Windows aufgerufen wird, um Messages auszuliefern) Event-Notifications von DirectShow zu empfangen. Wahrscheinlich ist es ausreichend, wenn ich die ggf. an diesem Window angekommenen Messages abarbeite, also Windows die Möglichkeit gebe diese WndProc aufzurufen. Wie macht man das?
Zuletzt geändert von RSE am Sa 26. Dez 2009, 01:30, insgesamt 1-mal geändert.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Alternative für Application.ProcessMessages in Library

Beitrag von RSE »

Ich habe im MSDN jetzt die Funktion PeekMessage gefunden, mit der ich offenbar für das Window anstehende noch unbehandelte Messages abrufen kann, bis keine mehr da sind und mir so quasi mein ProcessMessage selber bauen kann. Ich melde mich wieder, wenn ich es implementiert und getestet habe.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Alternative für Application.ProcessMessages in Library

Beitrag von RSE »

PeekMessage bringt leider keinen Erfolg. Ich hab es eingesetzt, bevor die Com-Interfaces freigegeben werden und bevor das Window zerstört wird. Gleiches Verhalten wie zuvor.

Ich hoffe es hat noch jemand eine Idee.
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

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: Alternative für Application.ProcessMessages in Library

Beitrag von marcov »

Nutze ein Callbackfunktion nach der Application der dort application.processmessages macht.

Weil eine Lösung mit PeekMessage igleich an der Basisfunktion von processmessages ist, tut processmessages mehr (zb synchronize() Abhandlung).

Und wenn mann mit peekmessages versucht, muss man den Handle des Main programs haben, und nicht der Handle des Libraries.

Generell wuerde ich auf Libraries verzichten wenn es moeglich ist, speziell wenn man dort auch LCL nutzt, bis es packages gibt.

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: Alternative für Application.ProcessMessages in Library

Beitrag von mschnell »

Application.ProcessMessages bearbeitet (durch Programm-internes kooperatives Multitasking) die Programm-interne Message-Queue. Alle Window-Messages erzeugen durch einen Library-Mechanismus zwar "Delphi-Language Queue-Messages", aber Queue Messages sind von einer anderen Natur als Windows Messages, weil sie die Mechanismen dieses Programm-internen kooperativen Multitaskings bedienen.

In einer mit mit Lazarus oder Delphi erzeugten DLL müsstest Du das (einzige!) "Application" Object des Main-Programs zur Verfügung haben, um "Application.ProcessMessages zu verwenden. U.U. kannst Du ja einen Pointer darauf an die DLL übergeben.
Wenn die DLL nicht in FPC (bzw Delphi) geschrieben ist, kannst Du vielleicht einen Pointer auf eine Funktion im Main-Program übergeben, die Du dann von der DLL aus aufrufen kannst und die "Application.ProcessMessages" macht.

-Michael

RSE
Beiträge: 462
Registriert: Mi 30. Jul 2008, 13:11
OS, Lazarus, FPC: WinXP SP3 (L 0.9.28.2 FPC 2.2.4)
CPU-Target: 32Bit
Kontaktdaten:

Re: Alternative für Application.ProcessMessages in Lib["gelöst"]

Beitrag von RSE »

marcov hat geschrieben:Und wenn mann mit peekmessages versucht, muss man den Handle des Main programs haben, und nicht der Handle des Libraries.

Generell wuerde ich auf Libraries verzichten wenn es moeglich ist, speziell wenn man dort auch LCL nutzt, bis es packages gibt.
Wie im Edit meines ersten Beitrages geschrieben, habe ich mir in der DLL direkt über WinAPI Aufrufe ein Window vom Betriebssystem Windows geholt, mit dem ich meine Messages von DirectShow selbst empfangen kann. Ich benutze also keine LCL. Mir geht es auch nicht unbedingt darum, dass das Hauptprogramm (die GUI) ihre Message Queue abarbeitet, sondern vielmehr darum, dass die Instanz des Betriebssystems, die für die Freigabe der referenzgezählten COM-Objekte zuständig ist, Rechenzeit bekommt. Da ist nach eurer Beschreibung Application.ProcessMessages wohl auch nicht zielführend.
mschnell hat geschrieben:kannst Du vielleicht einen Pointer auf eine Funktion im Main-Program übergeben, die Du dann von der DLL aus aufrufen kannst und die "Application.ProcessMessages" macht.
Das geht nicht, weil ich diesem Programmteil im Finalization eine Unit in der Library ausführe. Die Library wird in Form1.OnDestroy unloaded. Ich fürchte, dass es da durch ein Callback zu Problemen kommen kann, da evtl. Teile der Application schon freigegeben sind oder im Begriff sind freigegeben zu werden. Ich nehme an, mein Problem wird durch irgendwelche frühzeitigen Freigaben überhaupt erst ausgelöst.

Edit: Das Problem muss wohl doch anders gelöst werden. Ich habe jetzt im Form1.OnDestroy direkt vor dem UnloadLibrary ein Stop; eingebaut (stoppt die Wiedergabe und gibt alle COM-Interfaces frei) und schon schließt die Application problemlos, ohne jedes ProcessMessages und PeekMessage. Ich bin mal gespannt, ob ich des Pudels Kern noch finde...
Seit er seinen neuen Computer hat, löst er alle Probleme, die er vorher nicht hatte!

Antworten