Announcement

Collapse
No announcement yet.

XP und Modal bzw. Process Messages

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • XP und Modal bzw. Process Messages

    Unter XP gibt es definitiv arge Probleme mit Modalen Dialogen, wenn die Anwendung richtig ordentlich was zu tun hat, bisher war unsere Erfahrung, das sich das durch häufigeren Aufruf von Application.Processmessages umschiffen lässt, das klappt aber leider nicht immer. Z.B. bei größeren Datenbankabfragen, während denen das Programm keine Steuerung hat, kann man dieses ja gar nicht absetzen. Scheinbar hängt sich in diesem Fall die Message Qeue des Programmes auf. Das Hauptfenster wird auf einmal nicht mehr aktualisiert und vermittelt den Eindruck, es hätte sich aufgehängt. Wartet man lang genug, stellt man dann fest, das es sein Arbeit erledigt hat und der Schowmessage-Aufruf seine Message HINTER dem Fenster anzeigt. Das Hauptfenster wird weiterhin nicht aktualisiert, da hilft auch kein Aufruf von Application.Processmessages. Hat jemand eine Umschiffung für dieses Problem? Ach so, es handelt sich Anwendungen, die mit D5 Ent. geschrieben wurden.

  • #2
    Hallo,

    >.. bei größeren Datenbankabfragen, während denen das Programm keine Steuerung hat...

    Seit Windows 95 sagt die Win32-Knigge, dass derart langandauernde Aktionen in einen separaten Thread ausgelagert werden müssen, damit der primäre Thread die Windows-Botschaften fristgerecht verarbeiten kann. Mit jeder neueren Windows-Version "verschärft" Microsoft die Prüfungen auf Einhaltung der Knigge, d.h. wir werden immer stärker gezwungen, die Regeln auch wirklich einzuhalten.

    >Hat jemand eine Umschiffung für dieses Problem?

    Die einzige saubere Lösung besteht darin, <b>alle</b> langandauerenden Aktionen in einen zweiten Thread auszulagern

    Comment


    • #3
      Hmm, da wird dann aber irgendwie unnötiges auf den Programmierer abgeschoben, d.h. wir müssen fast jedes unserer Server- und Import- Programme umstricken, jeweils ein Thread für die Arbeit, damit der Hauptthread für die Oberfläche freibleibt, seufz. Und manche der Programme sind auch für Aussendienstler, teils mit Windows 98 Laptops, da kann der Schuss dann gleich wieder nach hinten losgehen, weil zwar Windows bedient wird aber die Ressourcen noch knapper werden... Naja trotzdem natürlich danke für den Hinweis

      Comment


      • #4
        Hallo,

        &gt;..da wird dann aber irgendwie unnötiges auf den Programmierer abgeschoben..

        nicht unbedingt. Wenn man ADO für den Zugriffsweg auf die Datenbank benötigt, machen das diese COM-Objekte von Microsoft völlig in eigener Regie, wenn die asynchrone Verarbeitung per Option beim Aufruf der Methode aktiviert wird. Der Entwickler bleibt auch dann immer nur in seinem primären Thread. Wenn allerdings der im Programm verwendete Datenbankzugriffsweg so etwas nicht automatisch macht, ist das in der Tat nun unserer Job

        Comment


        • #5
          Eine Dumme Frage fällt mir dazu dann doch noch ein: Wenn man sich nun einen Thread bastelt, der einfach nur alle paar Sekunden ProcessMessages aufruft, sollte man den doch in die verschiedenen Programme pflanzen können und diese ansonsten unverändert lassen. Das wäre deutlich weniger arbeit..

          Comment


          • #6
            Hallo,

            das würde nichts ändern, denn die Implementierung von ProcessMessages sieht wie folgt aus:
            <pre>
            function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
            var
            Handled: Boolean;
            begin
            Result := False;
            if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
            begin
            Result := True;
            if Msg.Message <> WM_QUIT then
            begin
            Handled := False;
            if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
            if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
            not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
            begin
            TranslateMessage(Msg);
            DispatchMessage(Msg);
            end;
            end
            else
            FTerminate := True;
            end;
            end;

            procedure TApplication.ProcessMessages;
            var
            Msg: TMsg;
            begin
            while ProcessMessage(Msg) do {loop};
            end;
            </pre>
            Und in der Hilfeseite zur Win32-API-Funktion <b>PeekMessage</b> aus dem Microsoft Platform SDK ist der folgende Satz zu finden: "<i>The PeekMessage function dispatches incoming sent messages, checks the <b>thread message queue</b> for a posted message, and retrieves the message (if any exist).</i>". Der Aufruf würde nur die Botschaftswarteschlange des Threads prüfen, aus dem der Aufruf erfolgt, aber nicht die Botschaftswarteschlange des primären Threads der VCL. Außerdem verwendet Borland in seiner Implementierung für das Fenster-Handle den Wert 0, so dass eine zweite Regel greift: "<i>If hWnd is NULL, PeekMessage retrieves messages for any window that <b>belongs to the current thread</b>. </i>". Da das Hauptfenster der Anwendung sowie das "versteckte" TApplication-Fenster immer aus dem primären Thread heraus erzeugt werden, kann auch wegen der 2. Regel das Ganze nicht funktionieren.

            P.S: Wenn man den Aufwand für die separaten Threads scheut, muss man zu einer Datenbank-Zugriffstechnologie greifen, die dies automatisch macht. Sowohl ADO als auch .NET (und somit auch ADO.NET) stellen einen derartigen Komfort zur Verfügung

            Comment

            Working...
            X