系统互斥体的 AbandonedMutexException 在第一次运行被杀死时未在第二次运行中捕获
Posted
技术标签:
【中文标题】系统互斥体的 AbandonedMutexException 在第一次运行被杀死时未在第二次运行中捕获【英文标题】:AbandonedMutexException for system mutex not caught on 2nd run when 1st run killed 【发布时间】:2012-02-01 05:26:07 【问题描述】:我创建了以下测试程序:
static void Main(string[] args)
using (var mutex = new Mutex(false, "foobar"))
Console.WriteLine("Created mutex");
try
try
if (!mutex.WaitOne(TimeSpan.FromSeconds(5), false))
Console.WriteLine("Unable to acquire mutex");
Environment.Exit(0);
catch (AbandonedMutexException)
Console.WriteLine("Mutex was abandoned");
Console.WriteLine("Acquired mutex - sleeping 10 seconds");
Thread.Sleep(10000);
finally
mutex.ReleaseMutex();
Console.WriteLine("Released mutex");
我的想法是我运行程序,当线程休眠 10 秒时,我通过任务管理器终止进程。下次我运行该过程时,我希望AbandonedMutexException
会在WaitOne()
调用中被捕获。但我没有看到输出“互斥锁被放弃”。
MSDN documentation 提到以下内容:
当一个线程放弃一个互斥体时,下一次抛出异常 获取互斥锁的线程。
但是,当我的进程被杀死(而不是同一应用程序中的另一个线程)时,操作系统似乎正在释放互斥锁。
有没有办法让我能够检测到以这种方式放弃的互斥锁?
【问题讨论】:
您是对的,当您的进程终止时,它的Mutex
es 也会终止。您是否尝试确定您的应用程序何时不正确关闭?
@M.Babcock - 我想我试图区分获得互斥锁的进程优雅结束或在有机会正确清理之前被杀死的情况。有没有办法做到这一点?
我不知道。如果这不能正常工作,那么我只允许应用程序的单个实例的逻辑将无法正常工作,所以我很高兴它可以按预期工作。 :)
【参考方案1】:
您观察到的是正确的行为。 From the documentation:
命名互斥体是一个系统对象,其生命周期受表示它的互斥体对象的生命周期限制。当第一个进程创建它的 Mutex 对象时,创建了命名的互斥锁;在此示例中,命名互斥锁由运行程序的第一个进程拥有。 当所有代表它的 Mutex 对象都被释放时,命名的 mutex 将被销毁。
如果您同时在两个单独的进程中运行您的程序(可能会增加超时时间)并杀死第一个进程,您可以观察到您的预期行为。当第一个进程被杀死时,它会放弃互斥锁,这使得第二个进程可以获取互斥锁,此时它会立即抛出 AbandonedMutexException。
如果您想确定您的进程是否正常退出,您需要一种不同的机制。您可以通过多种方式完成此操作,但最简单的方法之一是让进程在启动时在已知位置创建一个文件,并在正常清理后删除该文件。然后您可以检查该文件,如果找到该文件(并且没有正在运行的程序实例),您就知道上次关闭不是正常关闭或未成功完成。
【讨论】:
【参考方案2】:当有多个进程使用互斥体时,AbandonedMutexException 很有用。如果其中一个进程被杀死,另一个进程可以检测到这种情况。
但是,如果仅一个进程使用互斥锁,并且该进程被终止,则该互斥锁将从系统中删除(因为不再有对它的引用)。
【讨论】:
以上是关于系统互斥体的 AbandonedMutexException 在第一次运行被杀死时未在第二次运行中捕获的主要内容,如果未能解决你的问题,请参考以下文章
在没有互斥体的 C++11 中实现共享整数计数器的最简单方法: