Dude, where's my thread?? (or: rename a .NET thread pool thread - is it possible?)
Sometimes I find myself stepping through an application in Debug mode, until I hit 'step' on some particular line and it takes way too much time doing something, eating up 100% CPU. At this point, I hit the 'Break' button and try to find what's running that's taking so long.
The problem is, this app has a hefty amount of threads running, and at the time I hit 'Break', the execution point goes to the GUI thread that's probably just doing a 'Wait'. I then have to hunt through the existing 开发者_如何学JAVAthreads (I counted them - this time they're 37!) trying to find the one I was executing on. I'd have to look at the stack of every one of them until I find the one I was looking for.
The thread I'm running on is an async invoke, so it runs on a thread pool thread. I'd like to give this thread a descriptive name and reset its name at the end of the operation.
The problem is, property Thread.Name
can only be set once, afterwards it gives an InvalidOperationException
.
Any suggestions?
Oh yeah, I'm running VS2005/.NET 2.0 but I'm also curious if newer versions have better ways to handle this.
Define your own threadstatic property
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";
}
}
You can even write your own wrapper that automagically wraps your action / delegate / async callback in this using statement.
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);
Then when you stop the debugger, have a look at the contents of the variable ThreadMarker.ThreadNames and you will see which managed threads are stuck in your named handlers.
精彩评论