Получение списка текущих активных управляемых потоков в .NET? - PullRequest
29 голосов
/ 01 декабря 2009

Для функции типа «информация журнала для поддержки» я хотел бы перечислить и вывести информацию об активном потоке.

Мне хорошо известен тот факт, что в условиях гонки эта информация может быть неточной, но я хотел бы попытаться получить наилучший возможный результат, даже если она не на 100% точна.

Я посмотрел на Process.Threads, но он возвращает объекты ProcessThread, я хотел бы иметь коллекцию объектов Thread, чтобы я мог записывать их имя и узнать, являются ли они фоновыми потоками или нет.

Существует ли такая коллекция, даже если это просто снимок активных потоков, когда я ее называю?

т.

Thread[] activeThreads = ??

Заметьте, для ясности, я не спрашиваю о Process.Threads, эта коллекция дает мне много, но не все, что я хочу. Я хочу знать, сколько времени конкретные именованные потоки в нашем приложении используют в настоящее время (что означает, что мне придется взглянуть на соединение двух типов объектов позже, но имена важнее, чем время ЦП для начала).

Ответы [ 2 ]

16 голосов
/ 01 декабря 2009

Если вы хотите заменить Thread создания вашего приложения другим классом-оберткой, указанный класс-обертка может отслеживать активные и неактивные Thread s для вас. Вот минимальная работоспособная оболочка такой обертки:

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);
        }
    }
}

Не уверен, что вы можете пойти по такому пути, но он достигнет цели, если вы сможете подключиться на ранней стадии разработки.

4 голосов
/ 01 декабря 2009

Можно ли хранить информацию о потоках в поиске при создании каждого потока в приложении?

При запуске каждого потока вы можете получить его идентификатор, используя AppDomain.GetCurrentThreadId(). Позже вы можете использовать это для перекрестной ссылки с данными, возвращенными из Process.Threads.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...