程序终止自己进程的正确方法是什么(Windows)

Mat*_*att 2 .net windows kill process terminate

C#.NET 3.5

我有一个控制台应用程序,由计算机上的另一个应用程序调用.此控制台应用程序连续运行,并从"父"进程侦听stdin上的数据.

但是,当父项被停止或终止时,它启动的控制台应用程序将继续.在正常情况下,它使用最少的资源来等待来自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);
Run Code Online (Sandbox Code Playgroud)

这只是部分工作 - 它会停止CPU峰值,但如果我从Sysinternals精彩的进程监视器看我的进程,我可以看到DW20.exe运行 - "Microsoft应用程序错误报告"程序.它只是......坐在那里,控制台应用程序仍然在内存中.

我应该在这里做什么来正确终止进程以避免这种持续的CPU峰值和未释放的内存?最终这需要在没有干预的情况下运行.

PS我在这里使用命令行应用程序作为"长时间运行的程序"而不是Windows服务或Web服务,因为父程序只能配置为执行命令行应用程序,它通过stdin传递数据.(对于那些好奇的人来说,这是ejabberd,使用外部认证).

编辑:

等待stdin输入的代码是:

// Read data from stdin
char[] charray = new char[maxbuflen];
read = Console.In.Read(charray, 0, 2);
Run Code Online (Sandbox Code Playgroud)

在此之前我提到当父级终止时,控制台应用程序在CPU上疯狂.我从Visual Studio附加了一个调试器,实际上它仍然位于该行Console.In.Read上.理论上,当自我监视计时器触发并看到父项已经消失时,当另一个线程在Read()行上时,它会尝试System.Environment.Exit(0).

dev*_*uff 5

听起来你的进程进入了一个硬循环,因为当父进程退出时控制台输入流被关闭.你在检查返回值Console.In.Read吗?当流关闭时,它将返回零.在这一点上突破循环并让你的Main()方法自行退出.

如果你正在运行多个线程,他们必须先完成,使用Thread.Join或等效.