Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
122 views
in Technique[技术] by (71.8m points)

c# - Get list of threads

I want to list all running threads but not by using the List<> class. I want to dynamically observe running threads. How can I do that?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Method 1: Get OS Threads

This gets the list of OS threads:

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread thread in currentThreads)
{
}

Method 2: Get Managed Threads

Managed threads sit on top of OS threads. The IDs are different, and in theory, more than one Managed Thread may sit on top of a single OS thread (although I havn't actually observed this).

It turns out that getting managed threads is trickier than it really should be.

Method 2.1: Simplest code to get Managed Threads

  1. Check out Microsoft.Diagnostics.Runtime on GitHub.
  2. Install NuGet package CLR Memory Diagnostics (ClrMD).

You can then use said NuGet package to attach to your own process, and read the managed threads out:

using Microsoft.Diagnostics.Runtime;

using (DataTarget target = DataTarget.AttachToProcess(
    Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive))
{
    ClrRuntime runtime = target.ClrVersions.First().CreateRuntime();
    foreach (ClrThread thread in runtime.Threads)
    {
    }
}

Method 2.2: Example of how to search through managed threads by stack trace

Unfortunately, I couldn't find any way to search through the list of threads by the thread name.

However, all is not lost: here is an example of how to create a managed thread, then find it by searching through the stack frames for a match on the namespace, then print out its properties:

namespace MyTest
{
    int managedThreadId = 0;
    var task = Task.Run(
        () =>
        {
            // Unfortunately, cant see "Testing" anywhere in result returned
            // from NuGet package ClrMD ...
            Thread.CurrentThread.Name = "Testing";
            Thread.Sleep(TimeSpan.FromDays(1));
        });


    // ... so we look for our thread by the first word in this namespace.
    string startOfThisNamespace = this.GetType().Namespace.ToString().Split('.')[0]; // Is "MyTest".
    using (DataTarget target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive))
    {
        ClrRuntime runtime = target.ClrVersions.First().CreateRuntime();

        foreach (ClrThread thread in runtime.Threads)
        {
            IList<ClrStackFrame> stackFrames = thread.StackTrace;

            List<ClrStackFrame> stackframesRelatedToUs = stackFrames
                .Where(o => o.Method != null && o.Method.ToString().StartsWith(startOfThisNamespace)).ToList();

            if (stackframesRelatedToUs.Count > 0)
            {
                Console.Write("ManagedThreadId: {0}, OSThreadId: {1}, Thread: IsAlive: {2}, IsBackground: {3}:
", thread.ManagedThreadId, thread.OSThreadId, thread.IsAlive, thread.IsBackground);
                Console.Write("- Stack frames related namespace '{0}':
", startOfThisNamespace);
                foreach (var s in stackframesRelatedToUs)
                {
                    Console.Write("  - StackFrame: {0}
", s.Method.ToString());
                }
            }
        }
    }
}

You can also find the correct match by saving ManagedThreadId within the thread that you create, then looking for this same ID in runtime.Threads.

Testing

Tested with all combinations of:

  • Visual Studio 2015 SP1
  • .NET 4.5
  • .NET 4.6.0
  • .NET 4.6.1
  • C# 5.0
  • C# 6.0

References

See ClrMd throws exception when creating runtime.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...