【问题标题】:Best practice for naming a thread命名线程的最佳实践
【发布时间】:2014-06-14 03:46:49
【问题描述】:

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

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

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;

但那些第 3 方线程的实例将保持未命名,除非我创建下降线程类。是否有 Delphi Magic 将SetThreadName 设置为基线程类?我可以使用Detour.pas 来强制NameThreadForDebugging(FThreadName) 在Execute 方法的第一个位置被调用。

有什么想法吗?


更新 1 感谢 David 的热心帮助。为了帮助其他读者更好地理解我的问题,我对问题进行了巧妙的改写。

  1. 我的代码有什么问题?

    NameThreadForDebugging 方法实际上是一个静态方法。第二个参数ThreadId 是可选的,默认等于当前线程id。如果我没有明确给出ThreadId,我很可能会命名为当前线程,而不是我真正想要命名的线程。

  2. 解决办法是什么?

    在任何地方致电MyThread.NameThreadForDebugging('a_name', MyThread.ThreadId); 或在TMyThread.Execute 的开头致电NameThreadForDebugging('a_name');。

  3. 为什么要把事情做对这么困惑?

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

【问题讨论】:

  • 什么是FThreadName?不受您控制的第三方组件在哪里命名他们的线程?挂钩是最容易的部分。得到的名字不是那么多。
  • 如果我提供SetThreadName,它会为私有变量FThreadName设置一个名称。
  • 我不明白最后的评论。谁将提供这些名称,以及将在什么时候提供。
  • 关于你的编辑,绕道很容易。好吧,这当然是可能的,我们不要担心如何去做。虽然我不认为我会绕道TThread,因为还有其他方法可以制作线程。我看不出谁会真正设置FThreadName。更不用说助手不能添加数据成员,只能添加方法。你似乎还没有理解我的意思。如果有人能够为线程提供名称,那么他们就可以直接调用NameThreadForDebugging。

标签: multithreading delphi debugging ide delphi-xe


【解决方案1】:

我在这里是即兴的,但在我看来,您似乎认为只能根据在该线程内执行的代码来命名该线程。但事实并非如此。为了命名一个线程,您只需要它的 ID。

documentation 给出函数签名如下:

class procedure NameThreadForDebugging(AThreadName: AnsiString; 
  AThreadID: TThreadID = TThreadID(-1)); static;

如果您不提供可选的线程 ID 参数,则传递 -1,这被解释为含义,正在执行的线程。到目前为止,这就是您使用NameThreadForDebugging 的方式。但是,您可以只传递线程 ID。由于您显然有线程实例,因此您手头也有它们的 ID。

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

Thread.SetThreadName(ThreadName);

你可以简单地写:

TThread.NameThreadForDebugging(ThreadName, Thread.ThreadID);

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

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;

坦率地说,我不认为我会遇到这样的麻烦。致电NameThreadForDebugging 似乎就足够了。

【讨论】:

  • 哦,是的!感谢您的热心帮助。我怎么会这么瞎?
  • 好吧,我花了很长时间才理解这个问题!
  • 如果 NameThreadForDebugging 不是静态方法,它可能有助于在预期的线程上下文中设置线程名称。
  • 它是类静态方法的原因正是因为它可以在没有TThread 的实例的情况下调用。它允许你命名不是TThread后代的线程。
猜你喜欢
  • 2010-10-14
  • 2011-08-09
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
  • 2022-11-10
  • 2010-10-09
  • 1970-01-01
  • 2014-06-04
相关资源
最近更新 更多