服务重启后获取互斥锁时获取异常

时间:2018-07-06 02:44:39

标签: c# mutex

我正在用C#编写Windows服务。它通过从线程调用Read()来连续从MSMQ读取:

public string Read()
    {
        try
        {
            if (!readMutex.WaitOne(100))
            {
                return null;
            }
            var message = queue.Receive();
            return (string)message.Body;
        }
        catch (Exception ex)
        {
            logger.Error("Exception:" + ex);
        }
        finally
        {
            readMutex.ReleaseMutex();
        }

        return null;
    }

互斥锁是在类构造函数中创建的,并放置在析构函数中。

问题在于,在我停止并重新启动服务后,总是在第一次调用AbandonedMutexException时在if (!readMutex.WaitOne(100))处收到Read()

在附加调试器并添加断点之后,我发现当服务停止时,永远不会输入finally块,我不确定这是否是问题所在。

这可能不是一个大问题,因为下次调用Read()时,不再引发异常。但是我想知道是否有一种简单的方法可以解决这个问题?

追加1 : 我发现在服务停止时总是调用析构函数,因此我尝试在析构函数中释放互斥量。但是发现我不允许发布它,因为互斥锁似乎是在不同的线程上下文中获取的。

附加2 : 对于那些对此问题感兴趣的人,我将在检查发生了什么之后添加发现的内容。

我测试过,如果我创建一个无需释放互斥量就获取互斥量的程序,然后关闭该程序,则在下次运行该程序时,它仍然可以毫无例外地成功获取互斥量。这与该问题的症状相矛盾,也与我以前的想法相矛盾。

我认为事实是,当程序退出时,操作系统会为我关闭互斥锁,因此下次可以获取它。

但是为什么我的这项服务失败了?最终,我发现我还有另一个服务,它也创建了该路径的互斥体。第二个服务只是保留了一个互斥锁句柄,而没有对其进行任何操作(例如,等待它)。在这种情况下,当我的第一个服务重新启动并尝试再次获取Mutex时,它将获得异常。

最后,当程序以未发布的互斥锁终止时: 1)如果其他服务/应用程序也引用了互斥锁,则下次获取互斥锁时,将引发异常。 2)如果它是唯一引用此互斥锁的程序,则os将为我妥善处理此操作,并且在下次获取时不会报告任何错误。

1 个答案:

答案 0 :(得分:1)

readMutex.ReleaseMutex();很可能在服务关闭时永远不会被调用

更进一步,Receive一直阻塞直到收到消息为止,因此很有可能在服务关闭时超时,认为它已挂起,并杀死了进程而没有正常关闭。

这里有几种方法,

您最好在超时时呼叫MessageQueue.Receive Method (TimeSpan),并相应地调整逻辑,这样(关闭时)接收有望在服务超时之前超时。 / p>

另一种方法是在线程或任务中运行它,并在关机时将其杀死,并确保您调用readMutex.ReleaseMutex()

现在无论如何您都有足够的信息,并且您应该能够以适合自己的方式解决此问题

相关问题