Einzelnen Beitrag anzeigen

Benutzerbild von igel457
igel457

Registriert seit: 31. Aug 2005
1.622 Beiträge
 
FreePascal / Lazarus
 
#1

Synchronize und die Messagequeue

  Alt 2. Jan 2010, 18:41
Hallo,

ich habe ein kleines Problem mit den Methoden "TThread.Synchronize" bzw. "TThread.Queue". Ich verwende diese Methoden um Events aus meinem Audiosystem mit dem Hauptthread der VCL zu synchronisieren. Intern fügt "Synchronize" einen Record mit den Informationen über die übergebene Funktion zu einer Liste hinzu und sendet dann via "PostMessage" die Message WM_NULL an den Hauptthread. Wird dort WM_NULL empfangen so wird die Liste der zu synchronisierenden Methoden abgearbeitet. Soweit die Theorie.

Nun ergibt sich aber folgendes Problem: Scheinbar arbeitet meine Anwendung nur dann WM_NULL ab, wenn eine andere Message eintrifft - zum Beispiel wenn die Maus bewegt wird oder ein Timer-Event ausgelöst wird. Hierdurch stauen sich in meinem eigenen Synchronisierungsthread die "Anträge". Erst wenn man die Maus eine Weile über einem Fenster der Anwendung bewegt, werden die Events nach und nach abgearbeitet.

Hier ein kurzer Codeauszug:
Delphi-Quellcode:
procedure TAuSyncMgr.Execute;
begin
  try
    while not Terminated do
    begin
      while true do
      begin
        FCurMem := nil;
        FDeletedCurMem := false;

        FCritSect.Enter;
        try
          if FCallList.Count > 0 then
            FCurMem := PThreadMethod(FCallList[0]);
        finally
          FCritSect.Leave;
        end;

        if FCurMem = nil then
          break;

        try
          try
            {$IFNDEF DO_NOT_USE_VCL}
            //Erst nach dem Abarbeiten von "FCurMem^" durch Synchronize kehrt die Funktion zurück.
            //Das ist auch gut so. Jedoch wird FCurMem^ erst nach dem Eintreffen einer Windowmessage
            //wie "WM_MOUSEMOVE" abgearbeitet. Das ist nicht so schön.
            Synchronize(FCurMem^);
            {$ELSE}
            FCurMem^;
            {$ENDIF}
          finally
            if not FDeletedCurMem then
            begin
              //Remove the element from the list
              FCritSect.Enter;
              try
                FCallList.Delete(0);

                //Free the memory reserved for the method pointer
                FreeMem(FCurMem, SizeOf(TThreadMethod));
              finally
                FCritSect.Leave;
              end;
            end;
          end;
        except
          //
        end;
      end;
      Sleep(1);
    end;
  except
    //
  end;
end;
Den ganzen Code gibt es hier: http://audorra.svn.sourceforge.net/v...21&view=markup

Hat jemand eine mögliche Lösung für das Problem? Das Ganze sollte keine Änderung am Code des Endanwenders (sprich Formulare etc.) benötigen, sondern sich auf meinen Bibliothekscode beschränken. Einen Timer zu Formular hinzuzufügen (was übrigens zu langsam ist, da ich ca. 50-100 Events pro Sekunde auf diese Weise synchronisiere), ist also keine Lösung.

Ich hoffe mir kann hier jemand helfen.

Schon einmal Danke,
Andreas
Andreas
"Sollen sich auch alle schämen, die gedankenlos sich der Wunder der Wissenschaft und Technik bedienen, und nicht mehr davon geistig erfasst haben als die Kuh von der Botanik der Pflanzen, die sie mit Wohlbehagen frisst." - Albert Einstein
  Mit Zitat antworten Zitat