IDisposable, ObjectDisposedException и потокобезопасные типы - PullRequest
6 голосов
/ 11 февраля 2010

Есть ли смысл отслеживать классическое поле bool disposed в другом поточно-безопасном типе с целью условного выброса ObjectDisposedException в начале всех основных открытых методов?

Я видел этот шаблон, рекомендуемый в нескольких местах онлайн, но я не уверен, правильно ли его используют авторы, поэтому этот вопрос предполагает, что они есть.

В таком сценарииКажется, что единственный способ убедиться, что условие disposed истинно за пределами оценки условия, - это использовать механизм синхронизации, такой как lock (), по всему телу каждого открытого элемента, включая метод Dispose (bool).Не приведет ли это к тому, что тип снова станет однопоточным?

И если это так, то нет смысла использовать его, и поэтому вы не можете полагаться на механизм ObjectDisposedException в некоторых IDisposable.реализации - так почему бы нам НИКОГДА использовать этот механизм, если он не нужен?

====

Я думаю, IDisposable и ObjectDisposedException просто не идут вместе для потоковобезопасных типов.

Ответы [ 4 ]

4 голосов
/ 11 февраля 2010

Возможно, более эффективный способ сделать так, чтобы потокобезопасный объект не утилизировался во время работы метода, это использовать ReaderWriterLockSlim. Пусть все публичные методы получат блокировку чтения при выполнении и отпустят ее, когда они будут готовы. Пусть Dispose получит блокировку писателя. Он будет ждать, пока все другие методы не будут выполнены, прежде чем он получит блокировку записи. Затем он устанавливает isDisposed внутри блокировки записи, которую он содержит исключительно. Любые вызовы открытых методов после выполнения Dispose могут увидеть isDisposed и выдать ObjectDisposedException.

ReaderWriterLockSlim

http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

3 голосов
/ 11 февраля 2010

Если поведение вашего объекта будет другим, если он уже утилизирован, и если есть вероятность, что он будет использован после его утилизации, вам необходимо отслеживать это. Лучше бросить ObjectDisposedException, чем выбрасывать любое случайное исключение, которое произойдет, если объект уже удален, и вы не проверяете сначала.

0 голосов
/ 30 июля 2011

Если существует возможность вызова метода во время удаления объекта, семантика метода должна быть определена таким образом, чтобы вызов его для удаленного объекта не создавал проблем.В тех случаях, когда могут возникнуть или не возникнуть проблемы, следует использовать шаблон «попробуй / сделай».Если бы Microsoft следовала этому принципу с Control.BeginInvoke, то было бы и «Control.BeginInvoke», и «Control.TryBeginInvoke»;последний будет явно определен как возвращающий false и ничего не делающий, если элемент управления был удален до того, как действие было помещено в очередь (обратите внимание, что Control.BeginInvoke, возвращающий true, не гарантирует, что элемент управления не будет удален до того, как действие было фактически выполнено).Этот шаблон был бы очень полезен в таких вещах, как сценарии обновления дисплея: если элемент управления не расположен, я хочу запустить его процедуру обновления;однако, если оно будет утилизировано до запуска процедуры обновления, обновление станет спорным, и его сбой вряд ли станет проблемой.

0 голосов
/ 19 августа 2010

Учитывая, что логическое значение "Disposed" обновляется только в одном месте, и у вызывающей стороны есть ошибка использовать объект после того, как они вызвали Disposed.

Я думаю, что достаточно хорошо генерировать исключение ObjectDisposedException "большую часть времени" после вызова Dispose. Я вижу ObjectDisposedException как помощника по отладке, а не то, что должен поймать вызывающий объект.

...