我创建了以下测试程序:
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()
。但我不看到输出“Mutex被放弃了”。
MSDN documentation提及以下内容:
当一个线程放弃互斥锁时,下一个抛出异常 获取互斥锁的线程。
但是,当我的进程被杀死时(而不是同一个应用程序中的另一个线程),操作系统似乎正在释放互斥锁。
有没有办法让我能够检测出以这种方式放弃的互斥锁?
答案 0 :(得分:2)
您所观察到的是正确的行为。 From the documentation:
指定的互斥锁是一个系统对象,其生命周期由表示它的互斥锁对象的生命周期限定。当第一个进程创建其Mutex对象时,将创建指定的互斥锁;在此示例中,命名的互斥锁由运行该程序的第一个进程拥有。 当代表它的所有Mutex对象都已被释放时,已销毁已命名的互斥锁。
如果您同时在两个单独的进程中运行程序(可能会增加超时)并终止第一个进程,那么可以观察您的预期行为。当第一个进程被终止时,它会放弃Mutex,这允许第二个进程获取互斥锁,此时它会立即抛出AbandonedMutexException。
如果要确定您的进程是否正常退出,则需要不同的机制。您可以通过多种方式完成此任务,但最简单的方法之一是让进程在启动时在已知位置创建文件,并在正常清理后删除该文件。然后,您可以检查该文件,如果找到该文件(并且没有正在运行的程序实例),则表示上次关闭不正常或未成功完成。
答案 1 :(得分:1)
当有多个进程使用互斥锁时,AbandonedMutexException非常有用。如果其中一个进程被终止,另一个进程可以检测到这种情况。
但是,如果只有一个进程使用互斥锁,并且该进程终止,则从系统中删除互斥锁(因为没有更多的引用)。