考虑以下场景:我正在运行我的应用程序,该应用程序在执行期间必须运行另一个进程,并且只有在第二个进程完成内部特定初始化之后,我的第一个进程才能继续。例如:
...
// 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.OpenExisting 函数)
- AutoResetEvent - 这些对于任务来说是完美的,但是,在 .NET 下,这些似乎不能用于进程间通信。
- CreateEvent - 我可以使用 P/Invoke 和 Win32 CreateEvent 函数。理论上,它可以为我提供我需要的一切。但是,如果可能的话,我宁愿不使用 native 函数。
- 使用外部文件 - 最简单的方法就是使用一些操作系统外部对象(文件、注册表等)。然而,这似乎很老套。
我很高兴听到您对这个案例的意见。
谢谢!
最佳答案
我正要编辑 this answer , 但它似乎不正确。所以我会发布我自己的...
根据Threads for C#页面,里面有很多同步教程,AutoResetEvent
不能用于进程间同步。
然而,一个名为
EventWaitHandle
可用于进程间同步。
在上面的页面中,访问Creating a Cross-Process EventWaitHandle部分。
您设置它的方式很简单:
- 创建一个
EventWaitHandle
在流程 1 中,在开始流程 2 之前。 - 启动进程 2 后,调用
EventWaitHandle.WaitOne
阻塞当前线程。 - 最后,创建一个
EventWaitHandle
在进程 2 中调用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
取决于您的应用。
在我的例子中,我需要手动重置,因为我有许多进程连接到同一个进程。因此,一旦这个相同的进程完成初始化,所有其他进程都应该能够工作。因此, handle 应保持信号状态(无复位)。
对于您来说,如果您每次进程 1 启动进程 2 时都必须执行初始化,那么自动重置可能会有所帮助。
旁注:
InterprocessProtocol.EventHandleName
只是一个包装在 DLL 中的常量,process 1 和 process 2 引用。您不需要这样做,但它可以防止您输入错误的名称并导致死锁。
关于c# - 使用进程间同步对象同步 2 个进程 - Mutex 或 AutoResetEvent,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4123923/