Einzelnen Beitrag anzeigen

Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#4

AW: Hook für eigene Windows Message

  Alt 30. Jun 2010, 12:42
Hm, ich lasse mich gerne vom Gegenteil überzeugen und mir ein einfacheres Konzept unterbreiten Hier das Problem, welche ich erschlagen muss:

Ich habe einen LogController, der als Singleton-Pattern angelegt ist, d.h. ich hole mit die Instanz via einer statischen Klassenmethode TLogController.GetInstance() . Ich logge ebenso über eine statische Klassenmethode TLogController.Log( {Parameter} ); , die intern die GetInstance()-Methode verwendet.

Es gibt die Möglichkeit bei dem LogController EventListener zu registrieren, d.h. ich übergebe einen Zeiger auf eine Methode, die dann gecalled wird. Ebenso kann ich auch Module registrieren, die mehr Funktionalitäten bieten -- diese Module implementieren meinem Interface ILogModule. Ein Module ist im Moment z.B. das FileLogModule, welches, wie der Name schon sagt, die eintreffenden Logs in bestimmte Dateien schreibt.

Ganz wichtig ist, dass dieser LogController von mehreren Threads parallel benutzt werden kann und somit threadsicher sein muss. Ich habe in letzter Zeit schon mehrere Threads (hier im Forum ) geschrieben, die mir Lösungen zu diesem Problem geben sollten. So recht gefällt mir das mit diesem globalen Thread ja auch nicht. Jedenfalls habe ich im Moment nun folgendes Konzept: Die statische Klassenmethode Log() ist mit CriticalSections geschützt. Intern werden verschiedene Queues gefüllt -- für alle EventListener eine und für jedes Module separat eine. Danach wird die Nachricht WM_LOG_NOTIFIER (selbst definiert) via PostThreadMessage an den MainThread geschickt. Nun will ich ja, dass ich für den LogController keinerlei weiteren Code in das eigentliche Programm schreiben muss, da dies sonst Probleme beim Ändern oder Entfernen des LogControllers geben kann. Daher will ich in den MainThread auch nicht die passende Weiterleitung der Nachricht implementieren und mir bleibt nur der Weg über den globalen Hook.

Warum aber diese Nachricht? Das hat den Hintergrund, dass die EventListener und Module synchronisert benachrichtigt werden sollen (ohne Messages, da ich das bisherige Konzept beibehalten will), da teilweise auf die VCL zugegriffen werden kann. Die Message an den MainThread sorgt dafür, dass der Code für die Benachrichtigung auf unter dessen Kontext statt findet. Nachdem der MainThread ja unter Umständen auch mal blockiert sein kann (durch die CriticalSection in der Log()-Methode) ist eine Nachricht eben das/ein passende Mittel, um einen Deadlock zu umgehen -- weitere kenne ich im Moment leider nicht.

Ich habe im Moment aber auch noch die folgende Idee: Die Log-Methode wird komplett umgebaut, sodass darin in etwa folgendes steht (frei runtergeschrieben):
Delphi-Quellcode:
class procedure TLogController.Log(const AMessage: String; const ALogType: TLogType);
begin
  TThread.Synchronize(
    nil
    procedure()
    var
      LR : PLogRecord;
    begin
      New(LR);
      LR^.Text := AMessage;
      LR^.MsgType := ALogType;
      PostMessage(TLogController.Handle, WM_LOG_NOTIFIER, Integer(LR), 0);
    end
  );
end;
Die Idee hierbei ist es, dass ich dem TLogController ein Handle zur hand gebe und die Benachrichigung syncronisiert da hin schicke. Ich weiß nur leider nicht, ob das möglich ist, da ic das nur konzeptionell in meinem Kopf habe

Wenn jemand aber die super Idee hat, dann teile er sie mir doch bite mit Herzlichsten Dank!
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat