使用Mutex同步C#对象:“从非同步代码块调用对象同步方法”错误

时间:2012-09-21 22:30:14

标签: c# object synchronization mutex

我有一个C#应用程序代码,我在其中使用互斥锁在创建对象期间同步某些代码。对象构造函数获取互斥锁,并且仅在不再需要该对象时释放它(在应用程序关闭期间)。因此,释放互斥锁的一个位置将在对象析构函数中。出现的问题是有时我在对象析构函数中调用ReleaseMutex()时遇到异常。例外情况是:“对象同步方法是从未同步的代码块调用的”。看起来调用对象析构函数的gabage集合的线程有时与首先等待互斥锁(Mutex.WaitOne(false,namedMutex))的线程不同。如何在同一个线程上同步获取和释放互斥锁以避免此异常?谢谢你的帮助!

public class MyObject
{
    static ExtDeviceDriver devDrv;
    private Mutex mut = new Mutex(false,myMutex);

    public MyObject()
    {
        mut.WaitOne();
        //Thread safe code here.
        devDrv = new ExtDeviceDriver();
    }

    ~MyObject()
    {
        mut.ReleaseMutex();
    }
}

1 个答案:

答案 0 :(得分:4)

为什么不使用Dispose patternMutex继承自WaitHandleWaitHandle实施IDisposable。如果您有一个创建并使用IDisposable的类,那么它也应该实现IDisposable并妥善处置。不要让GC为您处理互斥锁,请在using块中手动执行此操作,或手动调用.Dispose()。通过这种方式,您可以随时了解谁在做什么,何时做什么。

This post引用了一句很棒的话:

  

如果对象实现了IDisposable,那么你应该考虑如何清理对象。

     

实现IDisposable的对象通常这样做是因为它们持有应该确定地释放的实际资源。

这正是这里发生的事情。

此外,我发现您正在使用命名的互斥锁。命名互斥锁用于跨进程,并作为操作系统句柄进行管理。是否有其他人获得相同的互斥量并试图释放它?你需要一个名为互斥的原因吗?这些通常很难处理,因为如果进程死亡并且互斥锁没有得到优雅处理,你可以放弃互斥锁和各种其他奇怪的东西。