C# 使用互斥体同步C“对象:”;对象同步方法是从未同步的代码块调用的;错误

C# 使用互斥体同步C“对象:”;对象同步方法是从未同步的代码块调用的;错误,c#,object,synchronization,mutex,C#,Object,Synchronization,Mutex,我有一个C#应用程序代码,在创建对象的过程中,我使用互斥来同步一些代码。对象构造函数获取互斥体,并仅在不再需要该对象时(在应用程序关闭期间)才将其释放。因此,释放互斥锁的一个位置是在对象析构函数中。出现的问题是,有时我在调用对象析构函数中的ReleaseMutex()时遇到异常。例外情况是:“对象同步方法是从未同步的代码块调用的”。似乎执行gabage收集(调用对象析构函数)的线程有时不是首先等待互斥体(mutex.WaitOne(false,namedMutex))的线程。如何在同一线程上同步

我有一个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();
    }
}
你为什么不使用这个工具呢
Mutex
继承自
WaitHandle
WaitHandle
实现
IDisposable
。如果您有一个类创建并使用了
IDisposable
,那么它还应该实现
IDisposable
,并正确地进行处理。不要让GC为您处理互斥锁,请使用块在
中手动处理,或在其上手动调用
.dispose()
。这样你就可以知道谁在做什么,什么时候做

有一句话你应该牢记在心:

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

实现IDisposable的对象通常这样做,因为它们保留着应该被确定释放的真实资源

这正是这里发生的事情

我还看到您正在使用一个命名的互斥。命名互斥体跨进程使用,并作为操作系统句柄进行管理。是否有其他人获得相同的互斥并试图释放它?您需要命名互斥体有什么原因吗?这些通常是很难处理的,因为如果进程死掉,互斥不能被优雅地处理,你可能会有大量的互斥和其他各种奇怪的东西

你为什么不使用
Mutex
继承自
WaitHandle
WaitHandle
实现
IDisposable
。如果您有一个类创建并使用了
IDisposable
,那么它还应该实现
IDisposable
,并正确地进行处理。不要让GC为您处理互斥锁,请使用
块在
中手动处理,或在其上手动调用
.dispose()
。这样你就可以知道谁在做什么,什么时候做

有一句话你应该牢记在心:

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

实现IDisposable的对象通常这样做,因为它们保留着应该被确定释放的真实资源

这正是这里发生的事情


我还看到您正在使用一个命名的互斥。命名互斥体跨进程使用,并作为操作系统句柄进行管理。是否有其他人获得相同的互斥并试图释放它?您需要命名互斥体有什么原因吗?这些通常是很难处理的,因为如果进程死掉,互斥不能被优雅地处理,你可能会有大量的互斥和其他各种奇怪的东西

你的互斥保护什么?什么是竞争?例如,如果你只在应用程序关闭时发布,你就不能什么都不做,让进程终止释放它吗?这是一种出于正确的原因使用错误的东西的情况,反之亦然。我忘了。在任何情况下,都需要在自己的线程上获取和释放同步对象。您对该对象的使用意味着您永远无法保证它确实会发生。换句话说,创建对象(因此,互斥对象)的线程可能已经消失,它可能已经停止,不再是,失去生命,并在天空的线程池中安息。如果您正在获取互斥,以便应用程序知道它已经在运行,那么没有理由释放它。否则,请[cont'd][cont'd]提供更多信息,也许我们可以了解您正在尝试做什么。不确定您在这里试图完成什么,但您的方法似乎有点可疑。你能解释一下你想做什么吗?你的互斥保护什么?什么是竞争?例如,如果你只在应用程序关闭时发布,你就不能什么都不做,让进程终止释放它吗?这是一种出于正确的原因使用错误的东西的情况,反之亦然。我忘了。在任何情况下,都需要在自己的线程上获取和释放同步对象。您对该对象的使用意味着您永远无法保证它确实会发生。换句话说,创建对象(因此,互斥对象)的线程可能已经消失,它可能已经停止,不再是,失去生命,并在天空的线程池中安息。如果您正在获取互斥,以便应用程序知道它已经在运行,那么没有理由释放它。否则,请[cont'd][cont'd]提供更多信息,也许我们可以了解您正在尝试做什么。不确定您在这里试图完成什么,但您的方法似乎有点可疑。你能解释一下你想做什么吗?这个应用程序可以在多个实例中运行。其目的是防止后续实例运行“devDrv=new ExtDeviceDriver()”,因此我需要一个命名互斥体,因为它在多个进程(实例)中可见。当此实例终止时,后续实例之一可以运行该行代码来处理外部驱动程序。Ok。您可能需要处理被放弃的互斥体,因为互斥体可能被保留在不一致的状态中