2010-07-26 197 views
2

我有打開子進程的父進程。只有當父進程不再運行時,我需要執行一些功能。父進程和子進程的關係

知道父進程沒有運行的最佳方式是什麼?因爲它可以被劇烈終止,所以我不想讓一些功能在關閉事件中向我的子進程發送信號。

或只是爲了尋找我這樣的父進程:

在父做這一點,並把它傳遞給孩子Process.GetCurrentProcess().Id 而在孩子的每幾毫秒檢查這一個

Process localById = Process.GetProcessById(1234); 

任何想法?建議..

+2

呃...通常它的父進程。除非你真的認識到你的過程的性別。乾杯。 – 2010-07-26 07:49:07

+0

@AOI Karasu:大聲笑,好點,我冒昧地改變這一點(如果性別很重要,請回復我的變化,Night Walker)。 – Abel 2010-07-26 07:53:43

+0

我剛剛發佈了一個用於.NET的子進程庫。 http://childprocess.codeplex.com/ – 2012-06-14 07:46:31

回答

4

下面是一個簡單的例子,如何使用Process.WaitForExit檢查其ID已經通過在命令行上的父進程:

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

使用Process.Exited事件可以這樣進行:

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

請注意,在這兩個樣本中,AutoResetEvent的目的僅僅是爲了防止您的主線程退出。在Windows窗體應用程序中,您不需要使用它,因爲您的程序將處於消息循環中,並且只有在關閉它時纔會退出。

+0

我已經使用了Process.Exited示例。真的非常感謝您的好解釋。 – 2010-07-26 15:54:39

4

底層的Win32進程句柄是可等待的,並且將在進程退出時發出信號。

在本地代碼:

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

在本機代碼,你需要要麼創建的WaitHandle定製亞型工藝處理,或使用的P/Invoke。 P/Invoke的缺點是難以合併(使用WaitForMultipleObjects多個等待,所以你不用專門用來等待一件事的線程)。


感謝0xA3:只要使用Process.WaitForExit(有一個超時,以避免無限期等待過載,並沒有這樣做對你的UI線程)。

+0

對不起,不是真的想去本地代碼。 – 2010-07-26 08:04:20

+1

@Night Walker:不需要這麼做,只需使用'Process.WaitForExit'。可能最好在一個單獨的線程。 – 2010-07-26 08:15:23

+0

@ 0xA3:有時MS已經爲你做了工作...... – Richard 2010-07-26 08:29:36

0

當父進程啓動子進程時,通過命令行參數將父進程ID傳遞給子進程。

然後在子進程中,使用Process.GetProcessById(int)獲取父進程並使用Process.WaitForExit()。或者,您可以使用Process.Exited事件在父進程退出時收到通知(請記住將Process.EnableRaisingEvents設置爲true,否則將不會引發該事件)。

0

我製作了一個子進程管理庫,其中父進程和子進程由於雙向WCF管道而受到監視。如果子進程終止或父進程終止,則通知對方。 還有一個可用的調試器助手,它可以將VS調試器自動附加到啓動的子進程。

雙向WCF通道是可擴展的,您可以處理進程啓動和進程終止事件。

項目選址:

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

的NuGet軟件包:

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