命名线程的最佳实践

sta*_*005 4 ide delphi debugging multithreading delphi-xe

最近我研究了一个高并发事件驱动框架(Java Akka),它将创建大量Actor线程.当我调试Akka应用程序时,线程具有非常有意义的名称.真的很棒.当我切换回Delphi时,我感到不安的是所有线程都没有命名,尽管它们在过去的20年里都没有命名.

对于我自己设计的所有线程类,我遵循这样一种模式,即我定义了一个setter SetThreadNameNameThreadForDebuggingExecute方法中调用.这到目前为止工作正常.

type
  TMyThread = class(TThread)
  private
    FThreadName: string;
  protected
    procedure Execute; override;
  public
    procedure SetThreadName(const ThreadName: string);
  end;

procedure TMyThread.SetThreadName(const ThreadName: string);
begin
  FThreadName := ThreadName;
end;

procedure TMyThread.Execute;
begin
  NameThreadForDebugging(FThreadName);
  // Put normal thread execution code here
end;
Run Code Online (Sandbox Code Playgroud)

但是,除非我创建了一个下降线程类,否则第三方线程的这些实例将保持未命名状态.是否有Delphi Magic设置SetThreadName为基类Thread类?我可以Detour.pas用来强制NameThreadForDebugging(FThreadName)Execute方法的第一个地方调用.

有任何想法吗?


更新1 感谢David的亲切帮助.为了帮助其他读者更好地理解我的问题,这个问题已被重新改写.

  1. 我的代码出了什么问题?

    NameThreadForDebugging方法实际上是一种静态方法.第二个参数ThreadId是可选的,默认情况下它等于当前的线程ID.如果我ThreadId不清楚,我可能很可能命名当前的线程,而不是我真正想要命名的线程.

  2. 解决办法是什么?

    MyThread.NameThreadForDebugging('a_name', MyThread.ThreadId);在任何地方打电话或NameThreadForDebugging('a_name');在开始时打电话TMyThread.Execute.

  3. 为什么让事情变得如此困惑?

    我不明白,为什么不提供没有第二个的非静态版本ThreadId.如果有这样的非静态版本,我就不会犯这个错误.

Dav*_*nan 7

我在这里进行了扩展,但它看起来好像你认为只能从该线程内执行的代码中命名一个线程.但事实并非如此.为了命名一个线程,你只需要它的ID.

文件给出了函数签名如此:

class procedure NameThreadForDebugging(AThreadName: AnsiString; 
  AThreadID: TThreadID = TThreadID(-1)); static;
Run Code Online (Sandbox Code Playgroud)

如果您不提供可选的线程ID参数,则-1传递被解释为含义的执行线程.NameThreadForDebugging到目前为止,您使用的是这种方式.但是,您只需传递线程ID即可.由于您明确拥有线程实例,因此您也可以拥有自己的ID.

您想象的接口涉及调用线程的实例方法传递线程的名称.那就是你想象写这段代码:

Thread.SetThreadName(ThreadName);
Run Code Online (Sandbox Code Playgroud)

您可以简单地写下:而不是这样做:

TThread.NameThreadForDebugging(ThreadName, Thread.ThreadID);
Run Code Online (Sandbox Code Playgroud)

如果你想使用类助手,你可以这样做:

type
  TThreadHelper = class helper for TThread
  public
    procedure SetThreadName(const ThreadName: string);
  end;

procedure TThreadHelper.SetThreadName(const ThreadName: string);
begin
  TThread.NameThreadForDebugging(ThreadName, ThreadID);
end;
Run Code Online (Sandbox Code Playgroud)

坦率地说,我不认为我会遇到这样的麻烦.通话NameThreadForDebugging似乎完全足够.

  • 它是类静态方法的原因正是如此,它可以在没有`TThread`实例的情况下调用.它允许您命名不是"TThread"后代的线程. (2认同)