C # .NET 3.5
У меня есть консольное приложение, которое вызывается другим приложением на компьютере. Это консольное приложение работает постоянно и прослушивает данные на stdin от «родительского» процесса.
Однако, когда родительский объект остановлен или уничтожен, запущенное им консольное приложение продолжается. При нормальных обстоятельствах он сидит и бездействует в ожидании ввода от стандартного ввода, используя минимальные ресурсы. Однако, как только родитель уходит, это консольное приложение нагружает процессор и истощает ядро, на котором оно работает, почти на 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);
Это работает только частично - это останавливает всплеск ЦП, но если я посмотрю на свои процессы из замечательного монитора процессов Sysinternals, то увижу, что работает DW20.exe - программа «Отчеты об ошибках приложения Microsoft». И он просто ... сидит там, и консольное приложение остается в памяти.
Что я должен сделать здесь, чтобы правильно завершить процесс, чтобы избежать этого непрерывного скачка ЦП и неизданной памяти? В конце концов это должно быть запущено без вмешательства.
P.S. Я использую приложение командной строки здесь как «долго работающую программу» вместо службы Windows или веб-службы, потому что родительская программа может быть настроена только для запуска приложения командной строки, для которого она передает данные через stdin. (для тех, кому интересно, это ejabberd, использующий внешнюю аутентификацию).
EDIT:
Код, ожидающий ввода от stdin:
// Read data from stdin
char[] charray = new char[maxbuflen];
read = Console.In.Read(charray, 0, 2);
Я уже упоминал, что когда родительский процесс завершается, консольное приложение сходит с ума на процессоре. Я подключил к нему отладчик из Visual Studio, и он, по сути, все еще находится на этой строке Console.In.Read. Теоретически, когда таймер самоконтроля срабатывает и видит, что родительский элемент отсутствует, он пытается System.Environment.Exit (0), когда другой поток находится в этой строке Read ().