在Delphi中检测辅助线程上下文

Mar*_*ski 4 delphi multithreading detect

在Delphi 2009和Windows API中,有没有办法检测特定代码段是否在辅助线程的上下文中运行?在伪代码中,我想能够说:

procedure DoSomething;
begin
  if InvokedBySecondaryThread then
    DoIt_ThreadSafeWay
  else
    DoIt_RegularWay;
end;
Run Code Online (Sandbox Code Playgroud)

这是我编写并已使用多年的日志库,现在我正在尝试适应可以从多个线程调用一个过程的情况.我的"常规方式"不是线程安全的.我知道如何使它线程安全,但我只想在实际需要时使用线程安全方法.

解释(不是必读的:-)

它归结为使用SendMessage和PostMessage将记录的消息分派给多个接收器(例如日志文件,控制台或VCL控件)之间的选择.使用PostMessage意味着在长时间阻塞操作正在进行时将不会收到消息,这有点违背了记录的目的,尤其是.用来表示进度.我想我可以用一个关键部分来保护SendMessage调用,但我再次希望只有在真正需要时才能这样做.

我知道system.pas中的全局变量IsMultiThread,但这只会告诉我应用程序已经启动了辅助线程.这些可能是由第三方库创建的线程,因此它们永远不会访问"我的"代码,因此它们的存在不会影响我的日志记录逻辑.

我真的希望我可以使用相同的低级库代码,无论它是从一个还是多个线程调用.例如,从辅助线程内部调用修改的线程安全日志记录过程很容易,但这会复制很多代码,我仍然要记住要做正确的事情.

@Lieven:目前,日志逻辑就像这样,有点简化了

我希望日志记录尽可能轻松,使用最少的设置代码并且不必担心管理对象生存期,因此库只暴露了许多重载的帮助程序,例如

procedure Log( const msgText : string; level : TLogLevel = lvNotice ); overload;
procedure Log( const msgText : string; Args : array of const; level : TLogLevel = lvNotice ); overload;
etc, including specialized routines that log a StringList, a boolean, an Exception and so on
Run Code Online (Sandbox Code Playgroud)

几乎所有其他事情都发生在单位的实施中.所有帮助程序最终都会调用

procedure _LogPostMessage( const msgText : string; level : TLogLevel );
Run Code Online (Sandbox Code Playgroud)

其中(a)检查单例调度程序对象是否已初始化; (b)创建一个TLogMessagePacket对象的实例(消息文本的容器,时间戳等),最后(c)执行SendMessage或PostMessage将"数据包"发送给调度程序(它有一个窗口句柄来接收它) ).

然后有一组来自抽象TLogReceiver类的类.一个这样的类接收记录的消息并将它们写入文件,另一个更新TMemo等.我实例化我想在项目中使用的具体接收器,并将它们与调度程序一起注册,调度程序从那时起拥有它们.

当调度员收到消息"数据包"时,它依次将其交给每个接收者,然后释放它.

所以我可能已经修复了上面的思考方式,这就是为什么当你说一个将调度程序对象交给日志库的代码应该根据线程上下文选择一个时,我不太明白你的想法.调度程序实际上是库的主要引擎,一次只存在一个.

klu*_*udg 14

  if GetCurrentThreadID = MainThreadID then begin
// in main thread
  end
  else begin
// in secondary thread
  end; 
Run Code Online (Sandbox Code Playgroud)