Give your threads meaningful names whenever possible, including the main thread. This will help you understand the output in the viewer (and also the debugger). If you don't name your threads, the viewer will generate names like "Thread 1" and
"Thread 2". A given thread can be named like this.
System.Threading.Thread.CurrentThread.Name = "Some Name";
The thread object's Name property is write-once, meaning an exception will be thrown if you try to assign it when it is not null. Therefore, you might want to test that the Name is null before assigning it.
The thread number column seen in the viewer is NOT the thread's ManagedThreadId property. I found that if you repeatedly create and destroy threads, the CLR uses the same ID numbers over and over. That is, newly created threads tend to get the same ManagedThreadId
as recently terminated threads. Since ManagedThreadId does not uniquely identify a thread for the life of a process, TracerX uses its own thread number, which is just a counter that is incremented every time it sees a new thread.
Testing has shown that when a ThreadPool thread is recycled,
- Its ManagedThreadId property remains the same.
- Its ThreadStatic storage remains allocated and associated with the thread.
- It's Name property is reset to null and a new name can (and should) be assigned.
When using ThreadPool threads, you should set the Name of every thread when you get it from the pool. This can cause a given thread's name to change several times over the life of the process, but that's OK as long as the name accurately reflects the
thread's purpose at any given time. The TracerX viewer allows you to filter by thread name or number.