Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logging and Synchronization

I have just written my own logging framework (very lightweight, no need for a big logging framework). It consists of an interface ILogger and a number of classes implementing that interface. The one I have a question about is TGUILogger which takes a TStrings as the logging target and synchronizes the logging with the main thread so that the Items member of a listbox can be used as the target.

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;

The logging works, but the application does not close properly. It seems to hang in the Classes unit. The stack trace:

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

What am I doing wrong here?

EDIT: I just found the following hint in the Delphi help for TThread.StaticSynchronize

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

This could be exactly my problem since some logging request come from the main thread. How can I solve this?

like image 310
jpfollenius Avatar asked Dec 05 '25 05:12

jpfollenius


1 Answers

If you compare the CurrentThreadID with MainThreadID then you can choose to synchronize or not.

Personally, I chose to have the GUI ask the log system for the latest info, rather than have threads pause. Otherwise your logging interferes with the fast operation of the thread which defeats the purpose of having it.

like image 140
mj2008 Avatar answered Dec 07 '25 21:12

mj2008