Чувак, где моя нить ?? (или: переименовать поток пула потоков .NET - возможно ли это?) - PullRequest
12 голосов
/ 25 января 2010

Иногда я обнаруживаю, что перебираю приложение в режиме отладки, пока не нажму «шаг» в какой-то конкретной строке, и это займет слишком много времени, делая что-то, съедая 100% ЦП. В этот момент я нажимаю кнопку «Перерыв» и пытаюсь найти то, что работает так долго.

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

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

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

Есть предложения?

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

1 Ответ

4 голосов
/ 25 января 2010

Определите ваше собственное свойство 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 / делегат / асинхронность в этом операторе 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 и видите, какие управляемые потоки застряли в именованных обработчиках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...