C# .NET 3.5
我有一个控制台应用程序正在被计算机上的另一个应用程序调用。此控制台应用程序持续运行,并从“父”进程侦听标准输入上的数据。
但是,当父级停止或终止时,它启动的控制台应用程序会继续运行。在正常情况下,它使用最少的资源等待来自标准输入的输入。但是,一旦父级离开,这个控制台应用程序就会使 CPU 达到峰值,并以接近 100% 的利用率使其运行的内核饿死。这一直持续到我手动终止该进程。
理想情况下,调用父母会自行清理,特别是因为这是在正常(非异常)“停止”条件下发生的。不幸的是,这个父进程不在我的掌控之中。
我的第一个想法是从控制台应用程序中获取调用父级,并监视其 PID。如果父进程消失,控制台应用程序将自行终止。目前,我正在这样做:
Process process = Process.GetCurrentProcess();
m_ParentPID = 0;
using (ManagementObject mgmtObj = new ManagementObject("win32_process.handle='" + process.Id.ToString() + "'"))
{
mgmtObj.Get();
m_ParentPID = Convert.ToInt32(mgmtObj["ParentProcessId"]);
}
string parentProcessName = Process.GetProcessById(m_ParentPID).ProcessName;
Log("Parent Process: " + parentProcessName + Environment.NewLine);
// Create a timer for monitoring self.
Timer timer = new Timer(new TimerCallback(sender =>
{
if (m_ParentPID != 0)
{
Process parent = System.Diagnostics.Process.GetProcessById(m_ParentPID);
if (parent == null)
{
Log("Parent process stopped/killed. Terminating self.");
System.Environment.Exit(0);
}
}
}));
// Kick on the timer
timer.Change(m_ExitWatcherFrequency, m_ExitWatcherFrequency);
虽然这只是部分起作用 - 它阻止了 CPU 峰值,但如果我从 Sysinternals 精彩的进程监视器查看我的进程,我可以看到 DW20.exe 正在运行 - “Microsoft 应用程序错误报告”程序。它只是......坐在那里,控制台应用程序保留在内存中。
我应该在这里做什么来正确终止进程以避免这种持续的 CPU 峰值和未释放的内存?最终,这需要在没有干预的情况下运行。
PS 我在这里使用命令行应用程序作为“长时间运行的程序”而不是 Windows 服务或 Web 服务,因为父程序只能配置为执行它通过标准输入传递数据的命令行应用程序。(对于那些好奇的人,这是 ejabberd,使用外部身份验证)。
编辑:
等待标准输入输入的代码是:
// Read data from stdin
char[] charray = new char[maxbuflen];
read = Console.In.Read(charray, 0, 2);
我之前提到过,当父级终止时,控制台应用程序在 CPU 上变得疯狂。我从 Visual Studio 中为它附加了一个调试器,事实上,它仍然位于 Console.In.Read 这条线上。理论上,当自我监控计时器触发并看到父级消失时,它会在另一个线程在该 Read() 行上时尝试 System.Environment.Exit(0)。