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

时间:2010-11-08 12:44:42

标签: c# .net synchronization pinvoke mutex

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

...
// 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. 使用外部文件 - 最简单的方法就是使用一些操作系统外部对象(文件,注册表等)。然而,这似乎相当骇人听闻。
  5. 我很高兴听到你对这个案子的意见。

    谢谢!

2 个答案:

答案 0 :(得分:15)

我只是想编辑this answer,但这似乎不正确。所以我会张贴自己的......

根据Threads for C#页面,其中包含大量同步教程,AutoResetEvent不能用于进程间同步。

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

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

流程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 引用。您不需要这样做,但它可以防止您错误输入名称并导致死锁。

答案 1 :(得分:11)

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

阅读创建跨进程EventWaitHandle部分...