使用进程间同步对象同步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) ...
我看到几个选项:
- Mutex – 在考虑进程间通信时会自动想到Mutex,但是,我看不到让Process1等待他自己生成的互斥锁的方法。 我可以使Process2创建一个互斥锁并等待Process1直到创建Mutex(使用轮询和Mutex.OpenExisting函数)
- AutoResetEvent – 那些对于任务来说是完美的,但是,似乎在.NET下这些不能用于进程间通信。
- CreateEvent – 我可以使用P / Invoke并使用Win32 CreateEvent函数。 从理论上讲,它可以为我提供我需要的一切。 但是,如果可能的话,我宁愿不使用本机函数。
- 使用外部文件 – 最简单的方法就是使用一些操作系统外部对象(文件,注册表等)。 然而,这似乎相当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.AutoReset
或EventResetMode.ManualReset
取决于您的应用程序。
就我而言,我需要手动重置,因为我有许多进程连接到同一进程。 因此,一旦初始化完成相同的过程 ,所有其他过程应该能够工作。 因此,手柄应保持信号状态(不复位)。
对于您来说,如果您必须在每次进程1启动进程2时执行初始化,则自动重置可能会有所帮助。
旁注: InterprocessProtocol.EventHandleName
只是一个包含在DLL中的常量,它包括进程1和进程2引用。 您不需要这样做,但它可以保护您不会错误输入名称并导致死锁。
我会考虑** AutoResetEvent **。 它们可以用于进程间通信,并且它们相对快速。 请参阅以下链接: c#的主题
阅读创建跨进程EventWaitHandle部分…