系统互斥锁的AbandonedMutexException在第一次运行被杀死时未在第二次运行时被捕获

时间:2012-02-01 05:26:07

标签: c# mutex

我创建了以下测试程序:

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提及以下内容:

  

当一个线程放弃互斥锁时,下一个抛出异常   获取互斥锁的线程。

但是,当我的进程被杀死时(而不是同一个应用程序中的另一个线程),操作系统似乎正在释放互斥锁。

有没有办法让我能够检测出以这种方式放弃的互斥锁?

2 个答案:

答案 0 :(得分:2)

您所观察到的是正确的行为。 From the documentation

  

指定的互斥锁是一个系统对象,其生命周期由表示它的互斥锁对象的生命周期限定。当第一个进程创建其Mutex对象时,将创建指定的互斥锁;在此示例中,命名的互斥锁由运行该程序的第一个进程拥有。 当代表它的所有Mutex对象都已被释放时,已销毁已命名的互斥锁

如果您同时在两个单独的进程中运行程序(可能会增加超时)并终止第一个进程,那么可以观察您的预期行为。当第一个进程被终止时,它会放弃Mutex,这允许第二个进程获取互斥锁,此时它会立即抛出AbandonedMutexException。

如果要确定您的进程是否正常退出,则需要不同的机制。您可以通过多种方式完成此任务,但最简单的方法之一是让进程在启动时在已知位置创建文件,并在正常清理后删除该文件。然后,您可以检查该文件,如果找到该文件(并且没有正在运行的程序实例),则表示上次关闭不正常或未成功完成。

答案 1 :(得分:1)

当有多个进程使用互斥锁时,AbandonedMutexException非常有用。如果其中一个进程被终止,另一个进程可以检测到这种情况。

但是,如果只有一个进程使用互斥锁,并且该进程终止,则从系统中删除互斥锁(因为没有更多的引用)。