zoukankan      html  css  js  c++  java
  • 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.

    1. What was wrong with my code?

      The NameThreadForDebugging method is actually a static method. The second parameter ThreadId is optional and it equals the current thread id by default.
      If I do not give a ThreadId clearly, I might very possibly name a the current thread, not the thread I really want to name it.

    1. What is the solution?

      Call MyThread.NameThreadForDebugging('a_name', MyThread.ThreadId);anywhere or Call NameThreadForDebugging('a_name'); at the beginning of TMyThread.Execute.

    2. 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;
  • 相关阅读:
    读书笔记之:高级Linux编程(ch14)
    读书笔记之:C++编程惯用法——高级程序员常用的方法和技巧
    读书笔记之:sed与awk
    读书笔记之:Linux——命令、编辑器与shell编程
    读书笔记之:C++必知必会
    读书笔记之:Linux程序设计(第4版)(ch17)
    读书笔记之:Linux管理员指南与Linux系统一本通
    读书笔记之:C++语言的设计与演化(2002)
    读书笔记之:Linux一站式学习
    读书笔记之:GNU/Linux编程指南
  • 原文地址:https://www.cnblogs.com/shangdawei/p/4014665.html
Copyright © 2011-2022 走看看