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

Synchronizing 2 processes using interprocess synchronizations objects - Mutex or AutoResetEvent(使用进程间同步对象同步 2 个进程 - Mutex 或 AutoResetEvent)
本文介绍了使用进程间同步对象同步 2 个进程 - Mutex 或 AutoResetEvent的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<代码>...//Process1 代码在这里进行各种初始化Process.Start("Process2.exe");//等到 Process2 完成其初始化,然后才继续(Process2 不退出)...

我看到了几个选项:

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

我很高兴听到您对此案的意见.

谢谢!

解决方案

我只是要编辑 这个答案,但这似乎不正确.所以我会发布我自己的...

根据Threads for C#页面,里面有很多同步教程,AutoResetEvent 不能用于进程间同步.<小时>但是,一个名为 EventWaitHandle 可用于进程间同步.在上面的页面中,访问 创建跨进程 EventWaitHandle 部分.p>

您的设置方式很简单:

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

流程 1

EventWaitHandle 句柄 = new EventWaitHandle(false,/* 创建无信号状态句柄 */EventResetMode.ManualReset,/* 忽略.此实例不会重置.*/InterprocessProtocol.EventHandleName/* 在共享程序集中定义的字符串.*/);ProcessStartInfo startInfo = new ProcessStartInfo("Process2.exe");使用 (Process proc = Process.Start(startInfo)){//等待进程2初始化.处理.WaitOne();//去做}

流程 2

//做一些冗长的初始化工作...EventWaitHandle 句柄 = 新 EventWaitHandle(false,/* 参数被忽略,因为句柄已经存在.*/EventResetMode.ManualReset,/* 下面解释.*/InterprocessProtocol.EventHandleName/* 在共享程序集中定义的字符串.*/);句柄.Set();//释放在句柄上等待的线程.

现在,关于 EventResetMode.您选择 EventResetMode.AutoReset 还是 EventResetMode.ManualReset 取决于您的应用程序.

就我而言,我需要手动重置,因为我有许多进程连接到同一个进程.所以,一旦这个同一个进程完成初始化,所有其他进程都应该能够工作.因此,句柄应保持在信号状态(无复位).

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

<小时>旁注: InterprocessProtocol.EventHandleName 只是一个包含在 process 1process 2 的 DLL 中的常量> 参考.您不需要这样做,但它可以防止您输入错误的名称并导致死锁.

Consider the following scenario: I'm running my application which, during its execution, has to run another process and only after that 2nd process finishes inner specific initialization, can my first process continue. 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)
...

I see several options:

  1. Mutex - Mutex comes to mind automatically when considering interprocess communication, however, I can't see a way of causing Process1 to wait for a mutex that he generated himself. I can cause Process2 to create a mutex and wait on Process1 till the Mutex is created (using polling and Mutex.OpenExisting function)
  2. AutoResetEvent - Those would be perfect for the task, however, in seems that under .NET these can't be used for interprocess communcation.
  3. CreateEvent - I can use P/Invoke and use Win32 CreateEvent function. In theory, it could provide me with everything I need. I'd rather not using native functions, however, if possible.
  4. Use external file - The easiest way would be just to use some OS external object (file, registry, etc). However, this seems rather hacky, however.

I'd be happy to hear your opinion for this case.

Thanks!

解决方案

I was just going to edit this answer, but it doesn't seem correct. So I'll post my own...

According to the Threads for C# page, which has a lot of synchronization tutorials, AutoResetEvent cannot be used for interprocess synchronization.


However, a named EventWaitHandle can be used for interprocess synchronization. In the above page, visit the Creating a Cross-Process EventWaitHandle section.

The way you set this up is straight-forward:

  • Create an EventWaitHandle in process 1, before starting process 2.
  • After starting process 2, invoke EventWaitHandle.WaitOne to block the current thread.
  • Lastly, create an EventWaitHandle in process 2 and invoke EventWaitHandle.Set to release the waiting thread.

Process 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
}

Process 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.

Now, regarding the EventResetMode. Whether you choose EventResetMode.AutoReset or EventResetMode.ManualReset depends on your application.

In my case, I needed a manual reset because I have have many processes connecting to the same process. So, once this same process is done being initialized, all of the other processes should be able to do work. Thus, the handle should be left in a signaled state (no reset).

For you, an automatic reset might be helpful if you have to perform initialization for every time process 1 starts process 2.


Side note: The InterprocessProtocol.EventHandleName is just a constant wrapped up inside a DLL that both process 1 and process 2 reference. You do not need to do this, but it protects you from mis-typing the name and causing a deadlock.

这篇关于使用进程间同步对象同步 2 个进程 - Mutex 或 AutoResetEvent的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)