web-dev-qa-db-ja.com

.NETで現在アクティブな管理対象スレッドのリストを取得していますか?

「サポート用のログ情報」タイプの関数の場合、アクティブなスレッド情報を列挙してダンプしたいと思います。

競合状態によってこの情報が半不正確になる可能性があることはよく知っていますが、100%正確でなくても、可能な限り最良の結果が得られるように努めたいと思います。

Process.Threadsを見ましたが、ProcessThreadオブジェクトが返されます。名前と、バックグラウンドスレッドであるかどうかをログに記録できるように、Threadオブジェクトのコレクションが必要です。

呼び出したときのアクティブなスレッドのスナップショットであっても、そのようなコレクションは利用できますか?

すなわち。

Thread[] activeThreads = ??

明確にするために、私はnot Process.Threadsについて質問していることに注意してください。このコレクションは私に多くのことを提供しますが、私が望むもののすべてではありません。アプリケーション内の特定の名前付きスレッドが現在どのくらいの時間を使用しているかを知りたい(つまり、後で2つのタイプのオブジェクトの接続を確認する必要がありますが、最初はCPU時間よりも名前の方が重要です)。

アプリケーションのThreadの作成を別のラッパークラスに置き換えても構わないと思っている場合、そのラッパークラスはアクティブおよび非アクティブのThreadsを追跡できます。このようなラッパーの最小限の実行可能なシェルは次のとおりです。

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

そのような道を進むことができるかどうかはわかりませんが、開発の初期段階で組み込むことができれば、目標は達成されます。

16
Jesse C. Slicer

アプリケーションで各スレッドを作成するときに、ルックアップにスレッド情報を格納することは可能ですか?

各スレッドが開始すると、AppDomain.GetCurrentThreadId()を使用してそのIDを取得できます。後で、これを使用して、Process.Threadsから返されたデータと相互参照できます。

4
Winston Smith