46

実行中のすべてのスレッドを一覧表示したいのですが、List<>クラスを使用しません。実行中のスレッドを動的に監視したい。どうやってやるの?

4

3 に答える 3

69

方法 1: OS スレッドを取得する

これは、OS スレッドのリストを取得します。

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread thread in currentThreads)
{
}

方法 2: マネージド スレッドを取得する

マネージド スレッドは、OS スレッドの上にあります。ID は異なります。理論的には、複数のマネージド スレッドが 1 つの OS スレッドの上にある可能性があります (ただし、実際にこれを確認したことはありません)。

マネージ スレッドを取得するのは、本来あるべきよりも難しいことがわかりました。

方法 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)
    {
    }
}

方法 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());
                }
            }
        }
    }
}

ManagedThreadId作成したスレッド内に保存し、 で同じ ID を探すことによって、正しい一致を見つけることもできますruntime.Threads

テスト

以下のすべての組み合わせでテスト済み:

  • ビジュアル スタジオ 2015 SP1
  • .NET 4.5
  • .NET 4.6.0
  • .NET 4.6.1
  • C#5.0
  • C#6.0

参考文献

ランタイムの作成時に ClrMd が例外をスローするを参照してください。

于 2016-02-22T16:02:36.383 に答える
59
using System.Diagnostics;

ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;

foreach (ProcessThread thread in currentThreads)    
{
   // Do whatever you need
}
于 2012-04-25T12:52:20.090 に答える