【发布时间】:2009-03-18 16:42:30
【问题描述】:
我刚刚编写了自己的日志框架(非常轻量级,不需要大型日志框架)。它由一个接口 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;
日志记录有效,但应用程序未正确关闭。它似乎挂在 Classes 单元中。堆栈跟踪:
System.Halt0、System.FinalizeUnits、Classes.Finalization、Classes.FreeExternalThreads、 System.TObject.Free、Classes.TThread.Destroy、Classes.TThread.RemoveQueuedEvents
我在这里做错了什么?
编辑:我刚刚在 TThread.StaticSynchronize 的 Delphi 帮助中找到了以下提示
Warning: Do not call StaticSynchronize from within the main thread. This can cause
an infinite loop.
这可能正是我的问题,因为一些日志记录请求来自主线程。我该如何解决这个问题?
【问题讨论】:
-
我不想回答题外话,但是如果你真的想使用它并且需要它轻量级,请考虑重新设计它,或者使用一些现成的日志库。这段代码有很多问题,远非轻量级。 mj2008 的回答是朝着正确的方向迈出第一步。
-
有趣的是,就在今天,我添加了一些与我自己的日志记录框架类似的东西(最终使用 SmartInspect 进行实际的日志记录)......
-
你添加了什么?希望通过调用 TGUILogger.Log() 不会出现同样的死锁可能性?
-
为什么是 TGuiLogger 之前的类?我假设一个错字,因为它不会编译。
-
@Gamecat:确实,我时不时会回到 C++ 习惯 @mghie:不是跑题。但是日志主要用于记录错误,因此这里的性能不是太关键。我只是想要一个简单易用的实现。
标签: multithreading delphi synchronization delphi-2009