List<>
クラスを使用せずに、実行中のすべてのスレッドを一覧表示したい。実行中のスレッドを動的に監視したい。どうやってやるの?
using System.Diagnostics;
ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;
foreach (ProcessThread thread in currentThreads)
{
// Do whatever you need
}
これにより、OSスレッドのリストが取得されます。
ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;
foreach (ProcessThread thread in currentThreads)
{
}
マネージスレッドはOSスレッドの上にあります。 IDは異なり、理論上は、複数のマネージスレッドが1つのOSスレッドの上にある場合があります(実際にはこれを観察していませんが)。
マネージスレッドを取得することは、実際に行う必要があるよりも難しいことがわかります。
次に、前述の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)
{
}
}
残念ながら、スレッド名でスレッドのリストを検索する方法を見つけることができませんでした。
ただし、すべてが失われるわけではありません。マネージスレッドを作成し、スタックフレームを検索して名前空間の一致を見つけ、そのプロパティを出力する方法の例を次に示します。
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
を保存し、runtime.Threads
でこの同じIDを検索することでも、正しい一致を見つけることができます。
以下のすべての組み合わせでテスト済み
ランタイムの作成時にClrMdが例外をスローする を参照してください。