+1 хороший ответ. К вашему второму пункту, и почему я решил реализовать его так, как я это сделал: я хотел, чтобы все журналы были в одном месте, чтобы я мог иметь регистраторы графического интерфейса, файловые регистраторы, регистраторы электронной почты и т. Д. Без изменения графического интерфейса. Я могу жить с не очень хорошей производительностью, если дизайн чистый и легко изменяемый.

ько что написал свой собственный каркас регистрации (очень легкий, нет необходимости в большом каркасе регистрации). Он состоит из интерфейса ILogger и ряда классов, реализующих этот интерфейс. Вопрос, о котором у меня есть вопрос, - это TGUILogger, который принимает TStrings в качестве цели ведения журнала и синхронизирует запись в журнал с основным потоком, так что элемент Items списка может использоваться в качестве цели.

type
  ILogger = Interface (IInterface)
    procedure Log (const LogString : String; LogLevel : TLogLevel);
    procedure SetLoggingLevel (LogLevel : TLogLevel);
  end;

type    
  TGUILogger = class (TInterfacedObject, ILogger)
  public
    constructor Create (Target : TStrings);
    procedure Log (const LogString : String; LogLevel : TLogLevel);
    procedure SetLoggingLevel (LogLevel : TLogLevel);
  private
    procedure PerformLogging;
  end;

procedure TGUILogger.Log (const LogString : String; LogLevel : TLogLevel);
begin
  TMonitor.Enter (Self);
  try
    FLogString := GetDateTimeString + ' ' + LogString;
    TThread.Synchronize (TThread.CurrentThread, PerformLogging);
  finally
    TMonitor.Exit (Self);
  end;
end;

procedure TGUILogger.PerformLogging;
begin
  FTarget.Add (FLogString);
end;

Регистрация работает, но приложение не закрывается должным образом. Кажется, висит в блоке классов. Трассировка стека:

System.Halt0, System.FinalizeUnits, Classes.Finalization, Classes.FreeExternalThreads, System.TObject.Free, Classes.TThread.Destroy, Classes.TThread.RemoveQueuedEvents

Что я здесь не так делаю?

РЕДАКТИРОВАТЬ: я только что нашел следующую подсказку в справке Delphi для TThread.StaticSynchronize

Warning: Do not call StaticSynchronize from within the main thread. This can cause 
an infinite loop.     

Это может быть именно моя проблема, так как некоторые запросы на вход в систему приходят из основного потока. Как я могу решить это?

Ответы на вопрос(2)

Ваш ответ на вопрос