c# - 获取 .NET 中当前事件的托管线程的列表?

标签 c# .net multithreading collections

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

我很清楚竞争条件会使此信息半不准确,但我想尝试获得尽可能好的结果,即使它不是 100% 准确。

我查看了 Process.Threads,但它返回 ProcessThread 对象,我想要一个 Thread 对象的集合,以便我可以记录它们的名称,以及它们是否是后台线程。

是否有这样的集合可用,即使它只是我调用它时事件线程的快照?

即。

Thread[] activeThreads = ??

请注意,要明确一点,我不是询问 Process.Threads,这个集合给了我很多,但不是我想要的全部。我想知道我们的应用程序中的特定命名线程当前使用了多少时间(这意味着我稍后将不得不考虑连接这两种类型的对象,但名称比开始时的 CPU 时间更重要。)

最佳答案

如果您愿意用另一个包装类替换应用程序的 Thread 创建,则该包装类可以为您跟踪事件和非事件的 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);
        }
    }
}

不确定你是否可以走这样的路线,但如果你能够在开发的早期阶段进行整合,它将实现目标。

关于c# - 获取 .NET 中当前事件的托管线程的列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1825882/

相关文章:

c# - yield return 和 LINQ Select 的不同结果

c# - 预期事件序列报告重复事件的测试助手

java - Java 中的多线程任务仅在 onClick Button 时工作一次

multithreading - 使用 bash 进行多线程

javascript - Datatables.net 渲染和应用分页速度慢

c# - 配置 IIS 7.0 元数据库问题

c# - 比 DialogResult 包含更多信息的自定义 ShowDialog

c# - 与 lambda 相比,C# 7 本地函数有哪些优势?

c++ - 线程安全的引用计数队列 C++

c# - 构建具有插件支持的应用程序