2010-07-26 7 views
2

J'ai un processus parent qui ouvre le processus enfant. Je dois effectuer certaines fonctionnalités uniquement lorsque le processus parent n'est plus en cours d'exécution.Processus parent et relation de processus enfant

Quelle est la meilleure façon de savoir que le processus parent n'est pas en cours d'exécution? Parce qu'il peut être terminé violemment alors je ne veux pas faire une fonctionnalité qui enverra un signal à mon processus de l'enfant sur l'événement de clôture.

Ou tout simplement à la recherche de mon processus parent comme ça:

Dans le parent en faire et le transmettre à l'enfant Process.GetCurrentProcess().Id Et chez l'enfant toutes les quelques millisecondes vérifier celui-ci

Process localById = Process.GetProcessById(1234); 

Toutes les idées ? Recommandations ..

+2

... Erm habituellement c'est un processus parent. Sauf si vous reconnaissez vraiment le genre de votre processus. À votre santé. –

+0

@AOI Karasu: lol, bon point, j'ai pris la liberté de changer cela (si le genre est important, s'il vous plaît revenir sur mes changements, Night Walker). – Abel

+0

Je viens de publier une bibliothèque de processus enfants pour .NET http://childprocess.codeplex.com/ –

Répondre

4

Voici un exemple simple comment utiliser Process.WaitForExit pour vérifier un processus parent dont l'identifiant a été transmis sur la ligne de commande:

using System; 
using System.Diagnostics; 
using System.Threading; 

class Program 
{ 
    static AutoResetEvent _autoResetEvent; 

    static void Main(string[] args) 
    { 
     int parentProcessId = int.Parse(args[0]); 

     _autoResetEvent = new AutoResetEvent(false); 

     WaitCallback callback = delegate(object processId) { CheckProcess((int)processId); }; 
     ThreadPool.QueueUserWorkItem(callback, parentProcessId); 

     _autoResetEvent.WaitOne(); 
    } 

    static void CheckProcess(int processId) 
    { 
     try 
     { 
      Process process = Process.GetProcessById(processId); 
      process.WaitForExit(); 
      Console.WriteLine("Process [{0}] exited.", processId); 
     } 
     catch (ArgumentException) 
     { 
      Console.WriteLine("Process [{0}] not running.", processId); 
     } 

     _autoResetEvent.Set(); 
    } 
} 

Utilisation de l'événement Process.Exited pourrait être fait comme ceci:

using System; 
using System.Diagnostics; 
using System.Threading; 

class Program 
{ 
    static AutoResetEvent _autoResetEvent; 

    static void Main(string[] args) 
    { 
     int parentProcessId = int.Parse(args[0]); 
     Process process = Process.GetProcessById(parentProcessId); 
     process.EnableRaisingEvents = true; 
     process.Exited += new EventHandler(process_Exited); 

     _autoResetEvent = new AutoResetEvent(false); 
     _autoResetEvent.WaitOne(); 
    } 

    static void process_Exited(object sender, EventArgs e) 
    { 
     Console.WriteLine("Process exit event triggered."); 
     _autoResetEvent.Set(); 
    } 
} 

Notez que dans les deux exemples, le but du AutoResetEvent est uniquement d'empêcher votre thread principal de quitter. Dans une application Windows Forms, vous n'avez pas besoin de l'utiliser car votre programme sera dans une boucle de message et ne sortira que si vous le fermez.

+0

J'ai utilisé l'exemple Process.Exited. Vraiment merci pour une bonne explication. –

4

La poignée de processus Win32 sous-jacente est attentiste, et sera signalé lorsque le processus se termine.

Dans le code natif:

DWORD res = WaitForSIngleObject(hProcess, INFINITE); 
if (res == WAIT_OBJECT_0) { 
    // process has exited. 
} 

Dans le code natif, vous devrez soit créer un sous-type personnalisé de WaitHandle pour poignées processus, ou utiliser P/Invoke. L'inconvénient de P/Invoke est qu'il est plus difficile à combiner (en utilisant WaitForMultipleObjects plusieurs attentes, donc vous ne dédiez pas un thread juste pour attendre une chose).


Merci à 0xA3: utilisez Process.WaitForExit (il y a une surcharge avec un délai d'attente pour éviter indéfinies, et ne le font pas sur votre thread d'interface utilisateur).

+0

Désolé, nous ne voulons pas vraiment aller au code natif. –

+1

@Night Walker: Pas besoin de le faire, utilisez simplement 'Process.WaitForExit'. probablement le meilleur dans un fil séparé. –

+0

@ 0xA3: Et parfois MS a déjà fait le travail pour vous ... – Richard

0

Lorsque le processus parent démarre le processus enfant, transmettez l'ID du processus parents à l'enfant via des arguments de ligne de commande.

Ensuite, dans le processus enfant, utilisez le Process.GetProcessById(int) pour obtenir le processus parent et utilisez Process.WaitForExit(). Vous pouvez également utiliser l'événement Process.Exited pour obtenir une notification lorsque le processus parent se termine (n'oubliez pas de définir Process.EnableRaisingEvents sur true, sinon l'événement ne sera pas déclenché).

0

J'ai fait une bibliothèque de gestion de processus d'enfant où le processus parent et le processus d'enfants sont surveillés en raison d'un tuyau de WCF bidirectionnel. Si le processus enfant se termine ou si le processus parent se termine l'un l'autre est notifié. Il existe également une aide de débogueur qui attache automatiquement le débogueur VS au processus enfant démarré.

Le canal WCF bidirectionnel est extensible et vous pouvez gérer les événements de début et de fin de processus.

site du projet:

http://www.crawler-lib.net/child-processes

NuGet Paquets:

https://www.nuget.org/packages/ChildProcesses https://www.nuget.org/packages/ChildProcesses.VisualStudioDebug/

Questions connexes