C#.NET 3.5
我有一个控制台应用程序正在被计算机上的另一个应用程序调用。此控制台应用程序持续运行,并从“父”进程的 stdin 上监听数据。
但是,当父级停止或终止时,它启动的控制台应用程序会继续。在正常情况下,它会闲置等待来自标准输入的输入,使用最少的资源。然而,一旦父进程离开,这个控制台应用程序就会使 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 峰值和未释放的内存?最终这需要在没有干预的情况下运行。
附言我在这里使用命令行应用程序作为“长时间运行的程序”而不是 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)。
最佳答案
听起来您的进程正在进入硬循环,因为当父进程退出时控制台输入流被关闭。您是否正在检查 Console.In.Read
的返回值?当流关闭时它将返回零。此时跳出循环并让您的 Main()
方法自行退出。
如果您正在运行多个线程,则必须首先使用 Thread.Join
或等效方法完成它们。
关于.net - 程序终止自身进程的正确方法是什么(Windows),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1200507/