NameThreadForDebugging -- Naming threads for debugging
http://forums.devart.com/viewtopic.php?t=16907
type tagTHREADNAME_INFO = record dwType : LongWord; // Must be 0x1000. szName : PAnsiChar; // Pointer to name (in user addr space). dwThreadId : LongWord; // Thread ID (-1=caller thread). dwFlags : LongWord; // Reserved for future use, must be zero. end; procedure NameThreadForDebugging (threadId: dword; threadName: AnsiString); const MS_VC_EXCEPTION = $406D1388; {$ifdef VER7P}
var tni : tagTHREADNAME_INFO;
{$endif} begin {$ifdef VER7P} if (threadName <> '') and (DebugHook <> 0) then begin tni.dwType := $1000; tni.szName := PAnsiChar(threadName); tni.dwThreadID := threadID; tni.dwFlags := 0; try RaiseException(MS_VC_EXCEPTION, 0, SizeOf(tni) div SizeOf(LongWord), @tni); except end; end; {$endif} end;
NameThreadForDebugging($FFFFFFFF, 'DBMonitor send thread')
http://stackoverflow.com/questions/23343765/best-practice-for-naming-a-thread
Best practice for naming a thread
Recently I worked on a high concurrent event-driven framework (Java Akka), which will create massive Actor
threads. When I debug an Akka application, threads have very meaningful names. It'd really awesome. When I switch back to Delphi, I feel upset that all threads are unnamed, although they are unnamed for the past 20 years already.
For all my own designed thread classes, I follow such a pattern that I define a setter SetThreadName
and I call NameThreadForDebugging
in the Execute
method. This works fine so far.
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;
But those instances of 3rd-party threads will stay unnamed, unless I create a descent thread class.
Is there Delphi Magic to set SetThreadName
to the base Thread class?
I can use Detour.pas
to force NameThreadForDebugging(FThreadName)
be called at the first place of Execute
method.
Any ideas?
Update 1 Thanks David for his kindly help. To help other readers to understand my question well, the question has been sightly rephrased.
-
What was wrong with my code?
The
NameThreadForDebugging
method is actually a static method. The second parameterThreadId
is optional and it equals the current thread id by default.
If I do not give aThreadId
clearly, I might very possibly name a the current thread, not the thread I really want to name it.
-
What is the solution?
Call
MyThread.NameThreadForDebugging('a_name', MyThread.ThreadId);
anywhere or CallNameThreadForDebugging('a_name');
at the beginning ofTMyThread.Execute
. -
Why so confused to make things right?
I do not understand, why not provide a non-static version without the second
ThreadId
. If there was such a non-static version, I could not have made this mistake.
I'm extemporising here, but it looks to me as though you believe that it is only possible to name a thread from code executing inside that thread.
But that is not the case. In order to name a thread all you need is its ID.
The documentation gives the function signature as so:
class procedure NameThreadForDebugging(AThreadName: AnsiString; AThreadID: TThreadID = TThreadID(-1)); static;
If you don't supply the optional thread ID parameter then -1
is passed which is interpreted as meaning, the executing thread.
Which is how you have been using NameThreadForDebugging
thus far. However, you can just pass the thread ID.
Since you clearly have thread instances, you also have their IDs at hand.
The interface that you have imagined involves calling an instance method of the thread passing the name of the thread.
That is you imagine writing this code:
Thread.SetThreadName(ThreadName);
Instead of doing that, you can simply write:
TThread.NameThreadForDebugging(ThreadName, Thread.ThreadID);
If you want to use a class helper you can do it like this:
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;
procedure TMainForm.FormCreate( Sender : TObject ); begin TThread.CurrentThread.NameThreadForDebugging( 'Main' ); TThread.NameThreadForDebugging( 'Main', MainThreadID ); TThread.NameThreadForDebugging( 'Main' ); end;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本