Frage

C# .NET 3.5

Ich habe eine Konsolenanwendung, die von einer anderen Anwendung auf dem Computer aufgerufen wird. Diese Konsolen -App wird kontinuierlich ausgeführt und hört Daten zu Stdin aus dem "Eltern" -Prozess zu.

Wenn der Elternteil jedoch gestoppt oder getötet wird, wird die von ihm begonnene Konsolen -App fortgesetzt. Unter normalen Umständen befindet es sich und im Leerlauf und wartet unter Verwendung von minimalen Ressourcen auf Eingaben von Stdin. Sobald der Elternteil verschwindet, verspannt diese Konsolen -App die CPU und verhungert den Kern, auf dem sie mit nahezu 100% Auslastung ausgeführt wird. Dies dauert fort, bis ich den Prozess manuell töte.

Im Idealfall würde der anrufende Elternteil nach sich selbst aufräumen, zumal dies unter normalen (nicht außergewöhnlichen) Stop -Bedingungen geschieht. Leider ist dieser übergeordnete Prozess nicht in meinen Händen.

Mein erster Gedanke war, den aufgerufenen Elternteil aus der Konsolen -App zu greifen und seine PID zu überwachen. Wenn der übergeordnete Prozess verschwindet, würde ich die Konsolen -App selbst enden. Derzeit mache ich das von:

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);

Dies funktioniert jedoch nur teilweise - es stoppt den CPU -Spike, aber wenn ich meine Prozesse von Sysinternals Wonderful Process Monitor betrachte, kann ich DW20.exe ausgeführt sehen - das Programm "Microsoft -Anwendungsfehler" -Programm. Und es sitzt nur ... dort und die Konsolen -App bleibt im Speicher.

Was soll ich hier tun, um den Prozess korrekt zu beenden, um diese kontinuierliche CPU -Spitze und den unveröffentlichten Speicher zu vermeiden? Schließlich muss dies ohne Intervention ausgeführt werden.

PS Ich verwende eine Befehlszeilenanwendung hier als "lang laufendes Programm" anstelle eines Windows -Dienstes oder -Webdienstes, da das übergeordnete Programm nur so konfiguriert werden kann, dass eine Befehlszeilen -App ausgeführt wird, für die Daten über stdin übergeben werden. (Für diejenigen, die neugierig sind, ist dies Ejabberd unter Verwendung einer externen Authentifizierung).

BEARBEITEN:

Der Code, der auf Eingaben von Stdin wartet, lautet:

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

Ich erwähne das vorher, wenn die übergeordneten Beendigung der Konsolen -App auf der CPU verrückt wird. Ich habe ihm einen Debugger von Visual Studio angehängt, und es sitzt tatsächlich immer noch auf dieser Linie -Konsole.in.read. Theoretisch versucht der selbstüberwachende Timer, wenn der selbstüberwachende Timer auslöst und der Elternteil verschwindet, ein System. Umwelt.exit (0) Wenn sich der andere Thread in dieser LEAD () -Linie befindet.

War es hilfreich?

Lösung

Es hört sich so an, als würde Ihr Vorgang in eine harte Schleife gehen, da der Konsoleneingabestream beim Ausgang des übergeordneten Abschlusses geschlossen wird. Überprüfen Sie den Rückgabewert von Console.In.Read? Es wird Null zurückkehren, wenn der Stream geschlossen wurde. Zu diesem Zeitpunkt brechen Sie aus der Schleife aus und lassen Sie Ihre Main() Methodenausgang von selbst.

Und wenn Sie mehrere Threads ausführen, müssen sie zuerst fertig sein, verwenden Thread.Join oder gleichwertig.

Andere Tipps

Verwenden Sie das Verlassen der Prozesse, um das Verlassen der Prozesse zu beobachten, die Verfahren Klasse und abonnieren Sie die Verlassen Veranstaltung.

Bearbeiten: Interop -Kommentar entfernt.

Bearbeiten (als Antwort auf Kommentare):

In den meisten Fällen ist das, was in einer solchen Situation getan wird, einige Daten wieder in die Übergabe, sodass Sie aufhören können, auf dem zu blockieren Console.In.Read Methodenaufruf.

Nehmen wir also an, Sie setzen eine Flagge, IsDone, zu wahr, wenn Sie entdecken, dass der übergeordnete Prozess durchgeführt wird. Da der Prozess, auf den Sie warten, nicht mehr etwas mehr senden, müssen Sie noch etwas für Standardeingaben erhalten, oder Sie werden für immer blockieren. Schreiben Sie also in Ihrem Event -Handler/Timer -Code etwas in die Standardeingabe Ihres eigenen Prozesses (er kann sogar ein besonderer Wert sein, um zu signalisieren, dass Sie fertig sind, wenn Sie möchten). Dadurch werden Sie an der Console.In.Read Methode. Überprüfen Sie, ob die feststellen, ob die IsDone Das Flag ist festgelegt - wenn ja, stoppen Sie die Verarbeitung und kehren Sie von Ihrer Hauptmethode zurück - nein - nein System.Environment.Exit erforderlich.

Ich würde dies lösen, indem ich Ihrer Konsolen -App einen Thread hinzufüge, der im Grunde genommen das Vorhandensein der aufrufenden App in der Prozesstabelle überwacht. Das ist alles von meinem Kopf, aber hier ist ein Pseudocode:

using System.Thread;
using System.Diagnostics;

main(){
     Thread monitoringThread = new Thread(new ThreadStart(monitor));
     monitoringThread.Name = "Monitor";
     monitoringThread.Start();
}

und im Funktionsmonitor:

void monitor(){
     Process[] theCallers = Process.GetProcessesByName("CallingProcessName");
     theCallers[0].WaitForExit();
     Process.GetCurrentProcess().Kill();
}

Angenommen, Sie haben nur einen Aufrufprozess in der Prozessliste, sobald dieser Prozess endet, wird dies auch sein. Sie können auch viel schöner Aufräumcode für Ihren eigenen Prozess einsetzen, anstatt ihn nur abrupt zu beenden.

Ich mag MMRs Idee, den übergeordneten Prozess vom Kind zu beobachten. Wenn Sie eine Möglichkeit haben, die PID des Elternteils in der Befehlszeile zu übergeben, wäre das noch besser. Aus dem übergeordneten Prozess können Sie die PID erhalten:

System.Diagnostics.Process.GetCurrentProcess().Id
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top