【问题标题】:Dude, where's my thread?? (or: rename a .NET thread pool thread - is it possible?)哥们,我的线呢?? (或:重命名 .NET 线程池线程 - 可能吗?)
【发布时间】:2010-01-25 17:22:10
【问题描述】:

有时我发现自己在调试模式下单步执行应用程序,直到我在某个特定行上单击“单步”,这需要太多时间做某事,占用 100% 的 CPU。在这一点上,我点击了“中断”按钮并尝试找出运行了这么长时间的运行。

问题是,这个应用程序有大量线程在运行,当我点击“Break”时,执行点转到可能只是在“等待”的 GUI 线程。 然后我必须搜索现有的线程(我数了一下——这次是 37 个!)试图找到我正在执行的线程。我必须查看每一个的堆栈,直到找到我要找的那个。

我正在运行的线程是异步调用,因此它在线程池线程上运行。 我想给这个线程一个描述性的名字,并在操作结束时重置它的名字。

问题是,属性Thread.Name 只能设置一次,之后它会给出InvalidOperationException

有什么建议吗?

哦,是的,我正在运行 VS2005/.NET 2.0,但我也很好奇新版本是否有更好的方法来处理这个问题。

【问题讨论】:

  • 为你的头衔点赞! (不是真的,好问题)

标签: c# .net debugging multithreading


【解决方案1】:

定义你自己的线程静态属性

public class ThreadMarker:IDisposable
{
  [ThreadStatic]
  private static string __Name;

  static Dictionary<int,string> ThreadNames=new Dictionary<int,string>();

  public static Name{get{return __Name;}}

  public ThreadMarker(string name)
  {
    lock(ThreadNames){
      ThreadNames[Thread.CurrentThread.ManagedThreadId]=name;
    }
    __Name=name; 
  }

  public void Dispose()
  {
    ThreadNames.Remove(Thread.CurrentThread.ManagedThreadId);
    __Name="Unowned";
  } 
}

您甚至可以编写自己的包装器,在此 using 语句中自动包装您的操作/委托/异步回调。

class NamedHandler<TArg>{
  public readonly Action<TArg> Handler;

  NamedHandler(string name,Action<TArg> handler){

    Handler=arg=>{
      using(new ThreadMarker(name)){
        handler(arg);
      }
    }     
  }
}

// usage
void doStuff(string arg){
  Log("Stuf done in thread {0} ",ThreadMarker.Name);
}    

ThreadPool.QueueUserWorkItem(new NamedHandler<string>("my Thread",arg=>DoStuff(arg)).Handler); 

然后,当您停止调试器时,查看变量 ThreadMarker.ThreadNames 的内容,您将看到哪些托管线程卡在您的命名处理程序中。

【讨论】:

  • 这将如何帮助识别调试器中的线程?它真的会取而代之的是这个属性吗?用于名称的内部字段是“m_Name”而不是“__Name”,它不是线程静态的。
  • 我为您的问题添加了一些代码。一旦线程运行,您将无法重命名线程。您可以做的是使用一个线程静态标记字段,您可以在冻结应用程序时检查该字段以查看哪个线程正在运行您的哪个处理程序。
猜你喜欢
  • 2010-10-10
  • 1970-01-01
  • 2011-08-10
  • 2018-10-02
  • 2011-11-23
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 2012-10-29
相关资源
最近更新 更多