进程退出时自动释放信号量
我正在使用信号量来限制我的应用程序可以运行的并发实例的数量。
进程终止的方式有很多种。是否可以创建信号量以便在进程退出时自动释放?
编辑:
我想要一些魔法来自动清理退出或崩溃时拥有信号量的进程的“引发”状态。无论如何,只是为了确保它被清除。
更多:
我正在寻找任何可行的选择,考虑到:
- 如果不需要外部应用程序来获取受保护应用程序的每个实例,那就太好了,
- 它不必是信号量 - 任何具有 COUNTER 的同步对象并且在所有者进程死亡时自动释放会很好,即使它是作弊的
- 我正在使用.NET 2.0,无法移动到该项目的较新版本,但可以使用 c/c++ 和互操作来利用某些东西,如果有东西
I am using Semaphore to limit the number of concurrent instances my application can run.
There are many ways a process can terminate. Can the Semaphore
be created so it automatically releases upon process exit?
EDIT:
I would like some magic to automatically clean up the semaphore 'raised' state for the process owning it upon exit or crash. Just to be sure that it is cleared, no matter what.
MORE:
I am looking for any viable option for it, considering:
- it would be great that NO external application is required to get a hold on every instance of the protected application
- it doesn't have to be Semaphore - any synchronization object that has COUNTER and is AUTOMATICALLY released upon death of a owner process will be fine, even if it's cheating
- I am using .NET 2.0, can't move to newer version on this project, but can use c/c++ and inter-op to leverage something if there is something
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以挂钩
AppDomain.ProcessExit
事件来执行任何清理操作,例如释放信号量。一般来说,命名信号量旨在协调跨进程的资源,而不考虑特定的进程生命周期。 .NET 中的信号量由本机 Windows 信号量对象支持,MSDN 说:
因此,正确的方法是在进程终止之前进行显式处理。
更新 - 要考虑的其他选项:
AppDomain.ProcessExit
事件中手动处理“紧急”释放不可行,请考虑创建一个IDisposable
包装器将在其构造函数中获取信号量并在Dispose
方法中释放它。更新 - 如果应用程序崩溃或强制终止(即通过任务管理器),
ProcessExit
将没有机会得到处理。因此,多个进程之间共享的任何非托管资源可能无法正确完成/处置/处理。请参阅本文了解更多信息细节。一个可行的选择可能是创建一个命名管道。命名管道的优点是一旦创建进程终止它们就停止退出。根据 MSDN:
有两个选项可以限制管道实例的数量:
nMaxInstances
参数中指定允许的实例数。当允许N
时,第N+1
进程将收到错误。You can hook into the
AppDomain.ProcessExit
event to perform any cleanup operations like releasing the semaphore.Generally, named semaphores are designed to coordinate resources across processes without taking particular process life-time into account. Semaphores in .NET are backed by native Windows semaphore objects, and the MSDN says:
Hence the right approach is explicit handling before process termination.
Update — Other options to consider:
AppDomain.ProcessExit
event, consider creating anIDisposable
wrapper that would acquire the semaphore in its constructor and release it in theDispose
method.Update — In case of an application crash or forced termination (i.e. via Task Manager)
ProcessExit
won't have a chance to be handled. Hence any unmanaged resources shared between multiple processes may not be finalized / disposed / handled correctly. See this article for further details.A viable option may be creating a named pipe. The advantage of named pipes is they cease to exit once the creating process is terminated. According to MSDN:
There are two options to limit the number of pipe instances:
FILE_FLAG_FIRST_PIPE_INSTANCE
flag in thedwOpenMode
argument it is possible to prohibit creation of multiple instances of the pipe. Then, the second process attempting to create the pipe will receive an error.nMaxInstances
argument. WhenN
are allowed, theN+1
st process will receive an error.适当的答案是在信号量周围实现“关键终结器”,以确保在所有情况下都能进行适当的清理。 ProcessExit 不保证在失败情况下执行,例如由于不可捕获的异常而强制卸载应用程序域(StackOverflowException 和 InvalidProgramException 是两个很好的例子。)
更多信息@ http://msdn.microsoft.com/en-us/library/system.runtime.constrainedexecution.riticalfinalizerobject.aspx,
引用:“公共语言运行时 (CLR) 保证所有关键的终结代码都有机会执行,前提是终结器遵循 CER 规则,即使在 CLR 强制卸载应用程序域或中止线程的情况下也是如此。 ”。
The appropriate answer is to implement a 'Critical Finalizer' around your semaphore to ensure proper clean-up in all cases. ProcessExit is not guaranteed to execute in a failure scenario, such as a forced appdomain unload due to non-trappable exceptions (StackOverflowException and InvalidProgramException being two good examples.)
More info @ http://msdn.microsoft.com/en-us/library/system.runtime.constrainedexecution.criticalfinalizerobject.aspx,
to quote: "the common language runtime (CLR) guarantees that all critical finalization code will be given the opportunity to execute, provided the finalizer follows the rules for a CER, even in situations where the CLR forcibly unloads an application domain or aborts a thread."
如果与 Daniel 不同,您可以将 NamedPipeServerStream 升级到 .Net 3.5 a> 类可用于创建您的管道。
我建议您在管道上保留静态引用,以避免退出进程之前完成。
管道的缺点是您不能等到实例可用而不进行轮询。
If, unlike Daniel, you can upgrade to .Net 3.5 a NamedPipeServerStream class is available to create your pipe.
I advice you to keep a static reference on the pipe to avoid Finalization before exiting the process.
The drawback of pipe is that you can't wait until an instance is available without polling.