代码之家  ›  专栏  ›  技术社区  ›  Lasse V. Karlsen

正在获取.NET中当前活动的托管线程的列表?

  •  29
  • Lasse V. Karlsen  · 技术社区  · 15 年前

    对于“支持日志信息”类型的函数,我想枚举和转储活动线程信息。

    我很清楚比赛条件会使这个信息变得半不准确,但我想尽量得到最好的结果,即使它不是100%准确。

    我查看了process.threads,但它返回process thread对象,我希望有一个线程对象集合,这样我就可以记录它们的名称,以及它们是否是后台线程。

    有这样一个集合可用吗,即使在我调用它时它只是活动线程的快照?

    IE.

    Thread[] activeThreads = ??
    

    注意,我很清楚 询问process.threads,这个集合给了我很多,但不是我想要的全部。我想知道应用程序中特定于时间的命名线程当前使用了多少时间(这意味着稍后我将不得不查看连接这两种类型的对象,但名称比CPU时间更重要。)

    2 回复  |  直到 10 年前
        1
  •  16
  •   Jesse C. Slicer    10 年前

    如果您愿意替换您的应用程序 Thread 使用另一个包装类创建的,所述包装类可以跟踪活动和非活动 螺纹 给你的。下面是这样一个包装器的最小可行外壳:

    namespace ThreadTracker
    {
        using System.Collections.Generic;
        using System.Collections.ObjectModel;
        using System.Threading;
    
        public class TrackedThread
        {
            private static readonly IList<Thread> threadList = new List<Thread>();
    
            private readonly Thread thread;
    
            private readonly ParameterizedThreadStart start1;
    
            private readonly ThreadStart start2;
    
            public TrackedThread(ParameterizedThreadStart start)
            {
                this.start1 = start;
                this.thread = new Thread(this.StartThreadParameterized);
                lock (threadList)
                {
                    threadList.Add(this.thread);
                }
            }
    
            public TrackedThread(ThreadStart start)
            {
                this.start2 = start;
                this.thread = new Thread(this.StartThread);
                lock (threadList)
                {
                    threadList.Add(this.thread);
                }
            }
    
            public TrackedThread(ParameterizedThreadStart start, int maxStackSize)
            {
                this.start1 = start;
                this.thread = new Thread(this.StartThreadParameterized, maxStackSize);
                lock (threadList)
                {
                    threadList.Add(this.thread);
                }
            }
    
            public TrackedThread(ThreadStart start, int maxStackSize)
            {
                this.start2 = start;
                this.thread = new Thread(this.StartThread, maxStackSize);
                lock (threadList)
                {
                    threadList.Add(this.thread);
                }
            }
    
            public static int Count
            {
                get
                {
                    lock (threadList)
                    {
                        return threadList.Count;
                    }
                }
            }
    
            public static IEnumerable<Thread> ThreadList
            {
                get
                {
                    lock (threadList)
                    {
                        return new ReadOnlyCollection<Thread>(threadList);
                    }
                }
            }
    
            // either: (a) expose the thread object itself via a property or,
            // (b) expose the other Thread public methods you need to replicate.
            // This example uses (a).
            public Thread Thread
            {
                get
                {
                    return this.thread;
                }
            }
    
            private void StartThreadParameterized(object obj)
            {
                try
                {
                    this.start1(obj);
                }
                finally
                {
                    lock (threadList)
                    {
                        threadList.Remove(this.thread);
                    }
                }
            }
    
            private void StartThread()
            {
                try
                {
                    this.start2();
                }
                finally
                {
                    lock (threadList)
                    {
                        threadList.Remove(this.thread);
                    }
                }
            }
        }
    }
    

    以及它的一个快速测试驱动程序(注意,我不迭代线程列表,只获取列表中的计数):

    namespace ThreadTracker
    {
        using System;
        using System.Threading;
    
        internal static class Program
        {
            private static void Main()
            {
                var thread1 = new TrackedThread(DoNothingForFiveSeconds);
                var thread2 = new TrackedThread(DoNothingForTenSeconds);
                var thread3 = new TrackedThread(DoNothingForSomeTime);
    
                thread1.Thread.Start();
                thread2.Thread.Start();
                thread3.Thread.Start(15);
                while (TrackedThread.Count > 0)
                {
                    Console.WriteLine(TrackedThread.Count);
                }
    
                Console.ReadLine();
            }
    
            private static void DoNothingForFiveSeconds()
            {
                Thread.Sleep(5000);
            }
    
            private static void DoNothingForTenSeconds()
            {
                Thread.Sleep(10000);
            }
    
            private static void DoNothingForSomeTime(object seconds)
            {
                Thread.Sleep(1000 * (int)seconds);
            }
        }
    }
    

    不确定您是否可以走这样的路线,但是如果您能够在开发的早期阶段进行合并,那么它将完成目标。

        2
  •  4
  •   Winston Smith    15 年前

    在应用程序中创建每个线程时,是否可以在查找中存储线程信息?

    当每个线程启动时,可以使用 AppDomain.GetCurrentThreadId() . 稍后,您可以使用它与返回的数据进行交叉引用。 Process.Threads .