【问题标题】:Is this the correct way to set a thread's name in Delphi 6?这是在 Delphi 6 中设置线程名称的正确方法吗?
【发布时间】:2012-02-23 18:54:30
【问题描述】:

我希望在 Delphi 6 IDE 中的线程列表窗口中显示一个用户友好的好名称。我在网上找到了以下代码,用于在 Delphi 6 中执行此操作,因为据我所知,该版本没有本地实现 SetThreadName()。我从线程的 Execute() 方法中调用它。我知道它被调用是因为 IDE 在引发异常时弹出。但是,当我查看线程列表 (Ctrl + Alt + T) 时,我没有看到我设置的名称。我只看到通常的线程 ID、状态、状态和位置列,没有别的。

我需要做些什么不同的事情才能让线程名称出现?另外,是否有人知道如何阻止 IDE 在 RaiseException 行上暂停?我的程序中有很多线程,每次运行程序时 IDE 都会弹出 N 次,这很烦人。
我知道我可以禁止 IDE 在 Delphi Exceptions 上停止,但我通常希望这样做,而且我不希望每次创建一组新线程时都必须关闭和打开它。

Named threads in Delphi - what is that for?

procedure SetThreadName_delphi(const Name: string);
    type
      TThreadNameInfo =
        record
          RecType: LongWord;
          Name: PChar;
          ThreadID: LongWord;
          Flags: LongWord;
        end;
var
    info:TThreadNameInfo;
begin
    // This code is extremely strange, but it's the documented way of doing it!

    info.RecType := $1000;
    info.Name := PChar(Name);
    info.ThreadID := $FFFFFFFF;
    info.Flags := 0;

    try
        RaiseException($406D1388, 0,
        SizeOf(info) div SizeOf(LongWord), PDWord(@info));
    except
    end;
end;

【问题讨论】:

  • 我相信线程名只在Delphi 2010及以上版本可见。
  • 不,从 D6 开始支持线程命名。
  • 从头开始 - Delphi 7.
  • 非常有用的一段代码!在 XE 中为我工作。谢谢让我们注意到这个。 Remy 提到的 NameThreadForDebugging 也同样有效。
  • 虽然这对于 Delphi 7-2007 版本是正确的,但记录的名称字段应该是 PAnsiChar 以支持较新的 Delphi 版本。

标签: multithreading delphi exception-handling


【解决方案1】:

我找到了the original code

这是一个特定于应用程序的异常(这意味着它特定于 Visual C++ 编译器)。我看不出为什么 Delphi 应该支持这个奇怪的功能(尽管这是可能的)。


编辑但它有效!(感谢 Remy Lebeau)

刚刚在 Delphi XE 上测试(我在调试器的“线程状态”窗口中看到“哇!”):

unit NameTest;

interface

uses
  Windows, Classes;

type
  TTestThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

implementation

{ TTestThread }

procedure SetThreadName_delphi(const Name: string);
    type
      TThreadNameInfo =
        record
          RecType: LongWord;
          Name: PAnsiChar;
          ThreadID: LongWord;
          Flags: LongWord;
        end;
var
    info:TThreadNameInfo;
    AnsiName: AnsiString;

begin
    AnsiName:= Name;
    info.RecType := $1000;
    info.Name := PAnsiChar(AnsiName);
    info.ThreadID := $FFFFFFFF;
    info.Flags := 0;
    try
        RaiseException($406D1388, 0,
        SizeOf(info) div SizeOf(LongWord), PDWord(@info));
    except
    end;
end;

procedure TTestThread.Execute;
begin
  SetThreadName_delphi('Wow!');
  while not Terminated do
    Sleep(1000);
end;

end.

【讨论】:

  • 是的,确实如此。线程命名是在 D6 中引入的,并且使用与 Visual Studio 完全相同的异常。
  • 它使用相同的魔法异常,以便delphi调试器可以显示以msvc编码的dll命名的线程的名称。
  • TThread 有一个静态的NameThreadForDebugging() 方法,该方法是在D2010 中引入的,因此您不再需要手动调用RaiseException()(它可以与非基于TThread 的方法一起使用)线程),例如:procedure TTestThread.Execute; begin NameThreadForDebugging('Wow!'); ... end;
  • @Serg - 我刚刚尝试了你的代码,这似乎与我使用 PAnsiChar(AnsiName) 而不是 PChar(Name) 发布的 sn-p 不同,我仍然 看不到线程名称(Delphi 6)。
  • 我做了更多的研究。 C++Builder v6 支持线程命名(我自己一直使用它),但 Delphi v6 不支持,即使它们共享相同的 RTL 和 VCL。该功能是在 Delphi v7 中添加的。
【解决方案2】:

从 C++Builder 6 和 Delphi 7 开始,File > New > Other > Thread Object 向导可以选择在调试器中命名新线程。该向导会在其Execute() 方法的顶部生成一个带有必要的RaiseException() 实现的存根TThread 后代类。

这对 Delphi 6 没有任何帮助,它还不支持线程命名。

【讨论】:

  • 我刚刚尝试过,生成的 Execute() 方法中唯一的内容是注释“在此处放置线程代码”。
  • 另外,我刚刚尝试了 Serg 的代码,这似乎与我使用 PAnsiChar(AnsiName) 而不是 PChar(Name) 发布的 sn-p 不同,我仍然 don 't 查看线程名称(Delphi 6)。
  • 显然直到 Delphi 7 才实现,抱歉。
  • 是的,我看到了您对其他回复的评论,非常感谢您的详细专业知识和帮助。
猜你喜欢
  • 1970-01-01
  • 2017-03-02
  • 2019-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 2018-03-25
相关资源
最近更新 更多