我希望我的子进程在其父进程退出时自行整理。目前我挂在 Process.Exited 方法上:
var parent = Process.GetProcessById(ParentPID);
parent.EnableRaisingEvents = true;
parent.Exited += ActOnParentExit;
我假设我需要保持parent
在范围内,直到我不再对 Exited 事件感兴趣。是这样吗?
我希望我的子进程在其父进程退出时自行整理。目前我挂在 Process.Exited 方法上:
var parent = Process.GetProcessById(ParentPID);
parent.EnableRaisingEvents = true;
parent.Exited += ActOnParentExit;
我假设我需要保持parent
在范围内,直到我不再对 Exited 事件感兴趣。是这样吗?
不, Process 类对此很聪明。它在内部使用 RegisteredWaitHandle 类。这主要用于确保引发 Exited 事件。但也保持对父对象的实时引用,因此它不会被垃圾收集。
框架中还有其他类也是这样工作的,使用各种方法来维护引用。Winforms 表单就是一个很好的例子,典型的 Winforms 应用程序从不保留对主表单的引用。它由一个将句柄映射到对象的内部表保持活动状态。关闭表单的用户会杀死将其从允许垃圾收集的表中删除的句柄。
System.Timers.Timer 是另一个,由 CLR 实际上知道并在启用计时器时保持引用的 cookie 对象保持活动状态。但不是 System.Threading.Timer 作为反例,如果您自己不保留对它的引用,它会在启用时收集垃圾。
您不必将 Process 实例保留在范围内,因为您有一个附加到事件的侦听器,因此它可以防止垃圾收集器释放您的实例。这是一个示例,演示了这一点:
private static void Main(string[] args)
{
Process.Start("notepad");
Console.WriteLine("Started notepad");
Wait();
Console.WriteLine("Wait complete");
Console.ReadKey();
}
private static void Wait()
{
Process myProcess = Process.GetProcessesByName("notepad").FirstOrDefault();
if (myProcess != null)
{
myProcess.EnableRaisingEvents = true;
myProcess.Exited += (sender, e) =>
{
Console.WriteLine("Notepad exited");
};
}
}
输出是:
Stared notepad
Wait complete
(用户关闭记事本)
Notepad exited