C#和C++进程间同步

7
我们有两个应用程序,一个是用C#编写的,另一个是用C++编写的。我们需要在这些进程之间维护一个计数器(在内存中)进行共享。每次其中一个应用程序启动时,它都需要检查此计数器并将其增加,并且每次应用程序关闭时,它都需要减少计数器。如果应用程序崩溃或使用任务管理器关闭,则还需要减少计数器。
我们考虑使用操作系统同步对象之一,例如MUTEX。
我的问题是:对于跨进程(其中一个是C#,另一个是C ++)最好使用哪种同步对象?

希望我的问题清楚明了。
非常感谢,

Adi Barda


我看到的主要问题是,你的需求说明如果程序崩溃,你希望值被减少。这将很难以任何可靠性实现。 - ScaryAardvark
Jon:从微软文档中我了解到,可以使用互斥锁来处理应用程序崩溃的情况:“……如果一个线程在拥有互斥锁时终止,则称该互斥锁被遗弃。互斥锁的状态被设置为已发信号,并且下一个等待的线程获得所有权。从 .NET Framework 2.0 版本开始,在获取遗弃的互斥锁的下一个线程中会抛出 AbandonedMutexException 异常。在 .NET Framework 2.0 版本之前,不会抛出任何异常……” - Adi Barda
@Jon。我不会把捕获所有异常视为崩溃。那是一个有序的关闭。虽然在面对意外情况时可能是有序的关闭,但它仍然不是崩溃。 即使安装“at_exit”处理程序等也无济于事。 你唯一能做的就是创建一个包装进程来监视真实进程的状态,如果它崩溃了,你可以减少计数器。但是如果你的包装进程死了会发生什么..... - ScaryAardvark
@Adi。是的,你可以使用互斥锁来保护共享计数器,但在面对崩溃时如何确保正确减少了它呢? - ScaryAardvark
@Jon。是的,这是一个恶性循环。正如我所指出的那样。谁在监视着这些监视者 :) - ScaryAardvark
显示剩余3条评论
3个回答

10
你可以尝试使用命名信号量(named semaphore)。信号量本质上是一个计数器,用于限制访问某些资源的线程/进程数量。通常工作方式如下:
  1. 创建一个最大计数为N的信号量。
  2. N个线程在其上调用等待函数WaitForSingleObject(或类似函数),并且它们都会继续执行而不会等待。每次内部信号量计数器会减少。
  3. 第N+1个线程也调用等待函数,但由于我们的信号量内部计数器现在为0,因此必须等待。
  4. 前N个线程中的一个通过调用ReleaseSemaphore函数来释放信号量。该函数会增加信号量的内部计数器。
  5. 等待线程现在无需等待,因此恢复执行,但是信号量计数器会回到0。

然而我认为这不是你想要使用它的方式。因此,你应该:

  1. 创建一个初始计数为零的命名信号量。
  2. 当应用程序启动时,立即释放它,从而增加计数器。您将在该调用期间获得以前的计数器值。
  3. 当应用程序结束时,调用WaitForSingleObject(hSemaphore, 0),从而减少计数器。0表示您不想等待。

这一切都相当容易实现。

C++代码示例:

//create semaphore
HANDLER hSemaphore = CreateSemaphore(NULL, 0, BIG_NUMBER, "My cool semaphore name");
//increase counter
LONG prev_counter;
ReleaseSemaphore(hSemaphore, 1, &prev_counter);
//decrease counter
WaitForSingleObject(hSemaphore, 0);

在C#中

using System.Threading;
//create semaphore
Semaphore sem = new Semaphore(0, BIG_NUMBER, "My cool semaphore name");
//increase counter
int prev_counter = sem.Release(); 
//decrease counter
sem.WaitOne(0);

名字和大数字显然应该是相同的。

如果这对你的任务不够,你将不得不研究共享内存并通过命名互斥锁对其进行访问限制,但这会稍微复杂一些。


信号量不是只适用于同一进程吗? - Adi Barda
2
事件、互斥对象、信号量和计时器可以具有名称,使它们在整个系统中可访问。http://msdn.microsoft.com/en-us/library/ms684292%28VS.85%29.aspx - vava
根据您的应用程序协议,您可以使用某种IPC来协商命名信号量(以防万一您选择的内容被其他进程使用)。 - C. Tewalt

1

信号量不是只适用于同一进程吗? - Adi Barda
1
不,正如你可能已经从vava对你其他评论的回复中知道的那样。 - Aryabhatta

1

请查看此线程,了解共享内存以进行同步的方法,或者在这里获取有关在.net/c#中进行同步的一些建议。

如果有可用的.net方法,则应适用于C++和C#。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接