Подтвердить что ты не робот

Чувак, где моя нить??? (или: переименуйте поток нитей потока .NET. Возможно ли это?)

Иногда я нахожу, что перехожу через приложение в режиме отладки, пока я не нахожу "шаг" на какой-то определенной строке, и слишком много времени делает что-то, едя на 100% процессор. На этом этапе я нажал кнопку "Break" и попытался найти, что работает так долго.

Проблема в том, что это приложение имеет огромное количество потоков, и в то время, когда я нажимаю "Break", точка выполнения переходит к потоку GUI, который, вероятно, просто выполняет "Wait". Затем мне нужно искать существующие потоки (я их подсчитал - на этот раз им 37!), Пытаясь найти ту, на которой я работал. Я должен посмотреть на стек каждого из них, пока не найду тот, который я искал.

Поток, который я запускаю, представляет собой вызов async, поэтому он запускается в потоке пула потоков. Я хотел бы дать этому потоку описательное имя и reset его имя в конце операции.

Проблема заключается в том, что свойство Thread.Name может быть установлено только один раз, после чего он дает InvalidOperationException.

Любые предложения?

О да, я запускаю VS2005/.NET 2.0, но мне также интересно, есть ли у более новых версий лучшие способы справиться с этим.

4b9b3361

Ответ 1

Определите собственное свойство threadstatic

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";
  } 
}

Вы можете даже написать свою собственную оболочку, которая автоматически завершает ваш ответ action/delegate/async в этом операторе 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, и вы увидите, какие управляемые потоки застревают в ваших именованных обработчиках.