使用进程间同步对象同步2个进程 – Mutex或AutoResetEvent

请考虑以下情形:我正在运行我的应用程序,在执行期间,必须运行另一个进程,并且只有在第二个进程完成内部特定初始化之后,我的第一个进程才能继续。 例如:

... // Process1 code does various initializations here Process.Start("Process2.exe"); // Wait until Process2 finishes its initialization and only then continue (Process2 doesn't exit) ... 

我看到几个选项:

  1. Mutex – 在考虑进程间通信时会自动想到Mutex,但是,我看不到让Process1等待他自己生成的互斥锁的方法。 我可以使Process2创建一个互斥锁并等待Process1直到创建Mutex(使用轮询和Mutex.OpenExisting函数)
  2. AutoResetEvent – 那些对于任务来说是完美的,但是,似乎在.NET下这些不能用于进程间通信。
  3. CreateEvent – 我可以使用P / Invoke并使用Win32 CreateEvent函数。 从理论上讲,它可以为我提供我需要的一切。 但是,如果可能的话,我宁愿不使用本机函数。
  4. 使用外部文件 – 最简单的方法就是使用一些操作系统外部对象(文件,注册表等)。 然而,这似乎相当hacky。

我很高兴听到你对这个案子的意见。

谢谢!

我只是想编辑这个答案 ,但这似乎不正确。 所以我会张贴自己的……

根据具有大量同步教程的Threads for C#页面, AutoResetEvent不能用于进程间同步。


但是,命名的EventWaitHandle可用于进程间同步。 在上面的页面中,访问Creating a Cross-Process EventWaitHandle部分。

你设置它的方式是直截了当的:

  • 在启动流程2之前,在流程1中创建EventWaitHandle
  • 启动进程2后,调用EventWaitHandle.WaitOne来阻止当前线程。
  • 最后,在进程2中创建一个EventWaitHandle并调用EventWaitHandle.Set来释放等待的线程。

过程1

 EventWaitHandle handle = new EventWaitHandle( false, /* Create handle in unsignaled state */ EventResetMode.ManualReset, /* Ignored. This instance doesn't reset. */ InterprocessProtocol.EventHandleName /* String defined in a shared assembly. */ ); ProcessStartInfo startInfo = new ProcessStartInfo("Process2.exe"); using (Process proc = Process.Start(startInfo)) { //Wait for process 2 to initialize. handle.WaitOne(); //TODO } 

过程2

 //Do some lengthy initialization work... EventWaitHandle handle = new EventWaitHandle( false, /* Parameter ignored since handle already exists.*/ EventResetMode.ManualReset, /* Explained below. */ InterprocessProtocol.EventHandleName /* String defined in a shared assembly. */ ); handle.Set(); //Release the thread waiting on the handle. 

现在,关于EventResetMode 。 是否选择EventResetMode.AutoResetEventResetMode.ManualReset取决于您的应用程序。

就我而言,我需要手动重置,因为我有许多进程连接到同一进程。 因此,一旦初始化完成相同的过程 ,所有其他过程应该能够工作。 因此,手柄应保持信号状态(不复位)。

对于您来说,如果您必须在每次进程1启动进程2时执行初始化,则自动重置可能会有所帮助。


旁注: InterprocessProtocol.EventHandleName只是一个包含在DLL中的常量,它包括进程1进程2引用。 您不需要这样做,但它可以保护您不会错误输入名称并导致死锁。

我会考虑** AutoResetEvent **。 它们可以用于进程间通信,并且它们相对快速。 请参阅以下链接: c#的主题

阅读创建跨进程EventWaitHandle部分…