记录和同步 [英] Logging and Synchronization

查看:163
本文介绍了记录和同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚写了我自己的日志框架(非常轻巧,不需要大的日志框架)。它由一个接口ILogger和一些实现该接口的类组成。我有一个问题的是TGUILogger,它将TStrings作为日志记录目标,并将日志记录与主线程同步,以便可以将列表框的Items成员用作目标。

  type 
ILogger = Interface(IInterface)
程序Log(const LogString:String; LogLevel:TLogLevel);
过程SetLoggingLevel(LogLevel:TLogLevel);
结束

type
TGUILogger = class(TInterfacedObject,ILogger)
public
构造函数Create(Target:TStrings);
procedure Log(const LogString:String; LogLevel:TLogLevel);
过程SetLoggingLevel(LogLevel:TLogLevel);
private
procedure PerformLogging;
结束

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

程序TGUILogger.PerformLogging;
begin
FTarget.Add(FLogString);
结束

日志记录工作,但应用程序未正确关闭。它似乎挂在班级单位。堆栈跟踪:



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



我在这里做错什么?



编辑:我刚刚发现以下提示Delphi帮助TThread.StaticSynchronize

 警告:不要在主线程内调用StaticSynchronize。这可能导致
无限循环。

这可能是我的问题,因为某些日志记录请求来自主线程。如何解决这个问题?

解决方案

如果没有找到更简单的方法,可以尝试这样做:



在程序初始化时,(从主线程),您的记录子系统调用Windows API函数GetCurrentThreadID并将结果存储在变量中。 (编辑:系统单元中的MainThreadID变量,在启动时为您自动初始化)谢谢,mghie。)当记录请求进入后,再次调用GetCurrentThreadID,只有当来自不同的线程才能同步。



还有其他不涉及Windows API的技巧,但最终会变得更加复杂,特别是如果您有一大堆不同的自定义TThread后代。基本原则是一样的,但是:在决定是否调用StaticSynchronize之前,验证是否处于主线程。


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?

解决方案

If you don't find any simpler way, you could try doing this:

At program initialization, (from the main thread,) have your logging subsystem call the Windows API function GetCurrentThreadID and store the result in a variable. (EDIT: the MainThreadID variable in the System unit, gets initialized this way automatically for you at startup. Thanks, mghie.) When a logging request comes in after that, call GetCurrentThreadID again, and only synchronize if it's coming from a different thread.

There are other tricks that don't involve the Windows API, but they end up being more complicated, especially if you have a bunch of different custom TThread descendants. The basic principle is the same, though: Verify whether or not you're in the main thread before you decide whether or not to call StaticSynchronize.

这篇关于记录和同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆