IDisposable и ReaderWriterLockSlim

У меня есть класс MyClass, Этот класс имеет поле: public ReaderWriterLockSlim rw; (публичный для более простого примера кода). Многие потоки могут читать данные из MyClass с помощью rw.EnterReadLock и т.п.

Также я реализовал 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 в ближайшем будущем, верно? (но дорогой ли этот ресурс класса?).
Может быть, я должен добавить некоторые блокировки (syncObject) в метод Dispose или что-то?

РЕДАКТИРОВАТЬ: также я имею дело с 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
}

1 ответ

Решение

Это может быть не самый лучший ответ, скорее наблюдения и некоторые мысли.

Вы можете упростить свой код? Я имею в виду, другие типы не должны заботиться о том, чтобы ваш тип вызывал исключения при определенных условиях параллелизма. Как вы это проверите? Общественная блокировка объекта - это зло. Это должно быть конфиденциально, если вы не хотите потратить месяцы, пытаясь выяснить таинственные ошибки.

Если вызывается метод dispose, это означает, что никакие другие объекты никогда не должны использовать этот объект. Это означает, что вы должны убедиться, что сначала все потоки закончили работать с объектом, прежде чем вызывать метод dispose.

Предложения

  • Сделайте замок приватным
  • Убедитесь, что все потоки завершены, прежде чем вызывать для удаления
  • Добавьте таймауты для безопасного поведения
  • Рассмотрите возможность использования статического объекта блокировки
  • ReaderWriterLockSlim не является дорогостоящим ресурсом (до того момента, когда вы должны заботиться о своем приложении)
  • Если ваш класс использует одноразовые ресурсы, обычно лучше внедрить IDisposable и избавиться от членов, которые должны быть уничтожены.
  • Не добавляйте никаких блокировок в метод Dispose, это будет просто. Это может привести к неприятным ошибкам. Потому что, если вы забудете вызвать Dispose вручную, он будет недетерминированно вызываться GC (через финализатор, который вы также должны добавить для вызова Dispose)
  • Правильный подход состоит в том, чтобы подождать, пока все потоки не будут выполнены, и избавиться от объекта.
Другие вопросы по тегам