【问题标题】:IDisposable and ReaderWriterLockSlimIDisposable 和 ReaderWriterLockSlim
【发布时间】:2013-01-18 06:09:44
【问题描述】:

我有一堂课MyClass。这个类有一个字段:public ReaderWriterLockSlim rw;(为了更简单的示例代码而公开)。许多线程可以使用rw.EnterReadLock等从MyClass读取数据。

我也实现了IDisposable接口:

private void Dispose (bool pDisposing)
{
    {
        if (pDisposing) // release managed resources
        {
            if (rw != null)
            {
                rwLockSlim.Dispose ();
                rwLockSlim = null;
            }
        }

        //--- release unmanaged resources
        // some code...
        isDisposed = true; // ...
    }
}

如您所见,问题是当第二个线程在 myClass 对象上调用 Dispose 时,一个线程正在使用 MyClass。我无法处置 ReaderWriterLockSlim,因为它会使我的应用程序崩溃。那么我应该删除那些释放托管资源的行吗?反正 ReaderWriterLockSlim 会在不久的将来被 GC 收集,对吧? (但是这个类的资源贵吗?)。
也许我应该在 Dispose 方法中添加一些 lock(syncObject) 或其他东西?

编辑:我也处理 AllocHGlobal,所以我需要等待,直到所有线程停止读取/写入 myClass

不同的观点:

public MyClass : IDisposable
{
            public void EnterReadLock (); // calls rwLockSlim.EnterReadLock,  
                                          // if object is disposed throws Exception

            public void ExitReadLock ();  // same as above

            public void Dispose ();       // wait until all threads exit from locks,
                                          // frees unamanged resources, mark class as disposed
}

【问题讨论】:

    标签: c# idisposable readerwriterlockslim


    【解决方案1】:

    这可能不是最好的答案,而是观察和一些想法。

    你能简化你的代码吗?我的意思是,其他类型不应该关心您的类型是否在特定并发条件下引发异常。你将如何测试这个?公共锁对象是邪恶的。它必须是私有的,除非你想花几个月的时间试图找出神秘的错误。

    如果调用了 dispose 方法,则意味着任何其他对象都不应该使用该对象。这意味着在调用 dispose 方法之前,您必须首先确保所有线程首先完成对对象的操作。

    建议

    • 将锁设为私有
    • 在调用 dispose 之前确保所有线程都已完成
    • 为安全行为添加超时
    • 考虑使用静态锁对象
    • ReaderWriterLockSlim 的资源并不昂贵(您应该在应用程序中关注这一点)
    • 如果您的类使用一次性资源,通常最好实现 IDisposable 并释放需要释放的成员。
    • 不要在 Dispose 方法中添加任何锁,它应该很简单。这可能会引入令人不快的错误。因为如果您忘记手动调用 Dispose,GC 将不确定地调用它(通过 finiliser,您也应该添加它以调用 Dispose)
    • 正确的做法是等到所有线程都完成后再释放一个对象

    【讨论】:

    • Public ReaderWriterLockSlim 仅用于示例目的。就像您在第二个示例中看到的那样,我创建了调用 rwLockSlim.EnterReadLock() 的方法 EnterReadLock()。无论如何,感谢您回答中的所有建议。
    • 我也会尽量避免这样的结构。据我所知,您似乎在多个线程中使用了 MyClass 类的单个实例,这很好。但是如果你这样做,那么让方法线程安全,不要依赖其他代码正确执行 EnterReadLockExitReadLock
    • 在某些情况下,人们希望在调用 Dispose 之前等待线程完成,但是有一些阻塞 API(用于通信等)其中 Disposeonly 可以在等待某事发生的对象上调用的方法(在某些硬件设备上,一旦请求操作,就无法取消它而不使设备处于无法使用的状态,直到设备已重新配置)。在该模式下,对繁忙的对象调用 Dispose 应该会导致正在进行的操作引发异常。
    猜你喜欢
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多