进程退出时自动信号量释放

时间:2011-03-08 11:03:07

标签: .net process semaphore

我正在使用Semaphore来限制应用程序可以运行的并发实例数。

流程可以通过多种方式终止。可以创建Semaphore,以便在进程退出时自动释放吗?

编辑:

我想要一些魔法来自动清除信号量“提升”状态,以便在退出或崩溃时拥有它。只是为了确保它被清除,无论如何。

MORE:

我正在寻找任何可行的选择,考虑:

  • 很高兴不需要外部应用程序来保护受保护应用程序的每个实例
  • 它不一定是信号量 - 任何具有COUNTER且在所有者进程死亡时自动释放的同步对象都可以,即使它是作弊
  • 我使用的是.NET 2.0,无法在这个项目上移动到更新的版本,但是如果有什么东西可以使用c / c ++和inter-op来利用某些东西

3 个答案:

答案 0 :(得分:6)

您可以挂钩AppDomain.ProcessExit事件来执行任何清除操作,例如释放信号量。

通常,命名信号量旨在协调跨进程的资源,而不考虑特定的进程生命周期。 .NET中的信号量由native Windows semaphore objects支持,MSDN说:

  

信号量对象在其最后一个句柄关闭时被销毁。关闭句柄不会影响信号量计数;因此,请务必在关闭句柄之前或进程终止之前调用ReleaseSemaphore。

因此,正确的方法是在流程终止之前进行明确处理。


更新 - 需要考虑的其他选项:

  1. 如果在AppDomain.ProcessExit事件中手动处理“紧急”释放是不可行的,请考虑创建一个IDisposable包装器,它将在其构造函数中获取信号量并在{{1}中释放它} 方法。
  2. 另一个问题是:Semaphore是否是这种情况的正确同步对象?一个简单的(命名的)互斥体不会更好用吗?

  3. 更新 - 如果应用程序崩溃或强制终止(即通过任务管理器),Dispose将无法处理。因此,可能无法正确地最终确定/处理/处理在多个进程之间共享的任何非托管资源。有关详细信息,请参阅this article

    可行的选择可能是creating a named pipe。命名管道的优点是,一旦创建过程终止,它们就会停止退出。根据MSDN:

      

    请注意,命名管道的实例可能有多个与之关联的句柄。当命名管道实例的最后一个句柄关闭时,总是删除命名管道的实例。

    有两个选项可以限制管道实例的数量:

    1. 只有一个实例:通过在ProcessExit参数中指定FILE_FLAG_FIRST_PIPE_INSTANCE标志,可以禁止创建多个管道实例。然后,尝试创建管道的第二个进程将收到错误。
    2. 更多实例:通过指定dwOpenMode参数中允许的实例数。如果允许nMaxInstancesN进程将收到错误。

答案 1 :(得分:4)

适当的答案是在您的信号量周围实施“关键终结器”,以确保在所有情况下进行适当的清理。 ProcessExit不保证在故障情况下执行,例如由于不可捕获的异常导致强制appdomain卸载(StackOverflowException和InvalidProgramException是两个很好的例子。)

更多信息@ http://msdn.microsoft.com/en-us/library/system.runtime.constrainedexecution.criticalfinalizerobject.aspx, 引用:“公共语言运行时(CLR)保证所有关键的终结代码都有机会执行,前提是终结器遵循CER的规则,即使在CLR强行卸载应用程序域或中止线程的情况下也是如此。“

答案 2 :(得分:1)

如果与Daniel不同,您可以升级到.Net 3.5,可以使用NamedPipeServerStream课程来创建pipe

  NamedPipeServerStream pipe;
  try
  {
    pipe = new NamedPipeServerStream(name, PipeDirection.InOut, 3);
  }
  catch (IOException)
  {
    //Maximum number of instances reached (3).
  }

我建议您在管道上保留静态引用,以避免在退出流程之前完成。 管道的缺点是你不能等到没有轮询的实例可用。