获取主题列表

san*_*p22 40 c# multithreading list

我想列出所有正在运行的线程,但不是通过使用List<>该类.我想动态观察正在运行的线程.我怎样才能做到这一点?

Con*_*ngo 53

方法1:获取操作系统线程

这将获得操作系统线程列表:

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread thread in currentThreads)
{
}
Run Code Online (Sandbox Code Playgroud)

方法2:获取托管线程

托管线程位于OS线程之上.ID是不同的,理论上,多个托管线程可能位于单个操作系统线程之上(尽管我实际上没有观察到这一点).

事实证明,获取托管线程比实际应该更棘手.

方法2.1:获取托管线程的最简单代码

  1. 在GitHub上查看Microsoft.Diagnostics.Runtime.
  2. 安装NuGet软件包CLR内存诊断程序(ClrMD).

然后,您可以使用所述NuGet包附加到您自己的进程,并读取托管线程:

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)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

方法2.2:如何通过堆栈跟踪搜索托管线程的示例

不幸的是,我找不到任何通过线程名称搜索线程列表的方法.

但是,一切都不会丢失:这里有一个如何创建托管线程的示例,然后通过在堆栈帧中搜索命名空间上的匹配项来查找它,然后打印出它的属性:

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}:\n", thread.ManagedThreadId, thread.OSThreadId, thread.IsAlive, thread.IsBackground);
                Console.Write("- Stack frames related namespace '{0}':\n", startOfThisNamespace);
                foreach (var s in stackframesRelatedToUs)
                {
                    Console.Write("  - StackFrame: {0}\n", s.Method.ToString());
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以通过ManagedThreadId在您创建的主题中保存,然后在中查找相同的ID来找到正确的匹配项runtime.Threads.

测试

测试了所有组合:

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

参考

请参阅ClrMd在创建运行时时抛出异常.


Xaq*_*ron 52

using System.Diagnostics;

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread thread in currentThreads)    
{
   // Do whatever you need
}
Run Code Online (Sandbox Code Playgroud)