对于“支持的日志信息”类型的函数,我想枚举并转储活动的线程信息。
我很清楚竞争条件会使这些信息半不准确,但我想尝试获得最佳结果,即使它不是100%准确。
我查看了Process.Threads,但是它返回了ProcessThread对象,我想要一个Thread对象的集合,这样我就可以记录它们的名字,以及它们是否是后台线程。
是否有这样的集合可用,即使它只是我调用它时活动线程的快照?
即
Thread[] activeThreads = ??
注意,要明确,我不询问Process.Threads,这个集合给了我很多,但不是我想要的全部。我想知道我们的应用程序当前正在使用多少时间特定的命名线程(这意味着我将不得不考虑稍后连接两种类型的对象,但名称比开始时的CPU时间更重要。)
答案 0 :(得分:16)
如果您愿意将应用程序的Thread
创建替换为另一个包装类,则表示包装类可以为您跟踪活动和非活动Thread
。这是一个这样的包装器的最小可行shell:
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);
}
}
}
不确定你是否可以选择这样的路线,但如果你能够在开发的早期阶段进行整合,它就能实现目标。
答案 1 :(得分:4)
在应用程序中创建每个线程时,是否可以在查找中存储线程信息?
每个线程启动时,您都可以使用AppDomain.GetCurrentThreadId()
获取其ID。稍后,您可以使用它来交叉引用从Process.Threads
返回的数据。