.NET 诊断 - II,使用 C# 的线程监控应用程序






3.10/5 (7投票s)
2001 年 1 月 17 日

216810

3496
使用 ProcessThread 类监控进程内线程的状态。
引言
这是本系列文章的第二篇,介绍如何使用 .NET SDK 中的 `System.Diagnostics` 类来获取正在运行的进程的信息。在我的第一篇文章“使用 .NET SDK 中的诊断类”中,我尝试创建一个应用程序,显示有关机器上正在运行的进程的一些静态信息。在这篇文章中,我将尝试解释另一个诊断类 `System.Diagnostic.ProcessThread` 的用法。顾名思义,它包含所有关于线程的信息。
关于进程创建和运行的基本概念在 .NET Framework 中保持不变。创建进程时,它从主线程开始。在这个主线程内,它可以根据需要创建任意数量的工作线程或 UI 线程,以优化和加速进程。诊断类 `Process` 提供有关进程内运行的线程的信息。您可以调用 `System.Diagnostics.Process` 类的 `Threads` 属性来获取 `System.Diagnostics.ProcessThrerad` 对象数组。以下代码显示了如何使用 `Process` 类的 `GetProcessByID` 方法获取 `Process` 对象,然后获取与该进程关联的线程。
public static ProcessThread [] GetProcessThreads (int nProcID)
{
try
{
Process proc = Process.GetProcessById (nProcID);
ProcessThread [] threads = proc.Threads;
return threads;
}
catch ( Exception e)
{
Console.WriteLine (e.Message);
return null;
}
}
`ProcessThread` 类公开了一组可用于获取有关线程的完整信息的属性。现在我们有了线程对象,我们可以使用它们来获取它们的属性,例如它们的 ID 和优先级。
线程的 ID 是什么?
每个线程在其存活期间都会被分配一个唯一的 ID。您可以调用线程的 `Id` 属性来获取此唯一 ID。
m_nThreadIDs[i] = m_Threads[i].Id;
线程的优先级是什么?
每个线程都有一个基本优先级。根据操作系统的分时分配和其他因素,此优先级在线程的整个生命周期中都会发生变化。此优先级可以从低至空闲状态,高至实时状态。您可以调用 `BasePriority` 和 `CurrentPriority` 属性来获取这些值。
m_Threads[i].BasePriority;
m_Threads[i].CurrentPriority;
当前线程状态是什么?
进程中创建的每个线程在其生命周期中都会更改其状态。它在任何给定时间都可能处于以下任何状态:已初始化、正在运行、等待等。`ProcessThread` 类的 `ThreadState` 属性提供了有关给定线程的当前状态信息。此属性返回一个枚举器 `ThreadState`。我在随附的实用程序类中提供了一个静态函数 `ThreadStateToString`,它将此枚举器转换为字符串。
m_ThreadStates[i] = m_Threads[i].ThreadState;
为什么线程处于等待状态?
当线程处于等待状态时,总有一些原因。您可以使用 `WaitReason` 属性来获取它。此属性返回一个枚举器 `ThreadWaitReason`。我的实用程序类中有一个静态函数 `ThreadWaitReasonToString`,它将此枚举器转换为字符串。这里需要提醒一下。**如果线程未处于等待状态,请勿调用 `ThreadWaitReason` 属性**。文档没有告诉你,但如果你在非等待线程上进行此调用,它会抛出异常。我在编写此应用程序时,亲身经历了这一点。
if (ThreadState.Wait == m_ThreadStates[i])
{
m_ThreadWaitReasons[i] = m_Threads[i].WaitReason;
}
线程运行了多长时间?
`ProcessThread` 类提供三个属性,这些属性将为您提供线程在操作系统内核、应用程序部分和总时间中花费的时间。这些属性分别是 `PrevilegedProcessorTime`、`UserProcessorTime` 和 `TotalProcessorTime`。
m_TotalProcessorTimes[i] = m_Threads[i].TotalProcessorTime;
线程监控应用程序
本文随附的代码是一个诊断应用程序,用于监控进程内运行的所有线程。我在应用程序中设置了一个计时器,每两秒更新一次线程状态。为了方便起见,您可以在 `MainAppForm` 构造函数中修改此值。
m_Timer.Interval = 2000;
此应用程序显示系统上所有当前正在运行的进程的列表。当您单击此列表中的一个进程时,右侧的列表视图开始显示该进程内运行的所有线程的状态。代码尚未针对由于每两秒刷新列表视图而发生的闪烁进行优化,但它可以工作。尝试使用此应用程序,看看任何进程的线程状态是如何显示的。