2010-02-11 3 views
6

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

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

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

И если это правда, тогда не было бы смысла его использовать, и поэтому вы не можете полагаться на механизм ObjectDisposedException в некоторых реализациях IDisposable - так почему бы нам ЭТО использовать этот механизм, если он не является " необходимо?

====

Я думаю IDisposable и ObjectDisposedException просто не идут вместе для поточно-типов.

+0

См. Также: http://stackoverflow.com/questions/170028/how-would-you-simplfy-entering-and-exiting-a-readerwriterlock –

ответ

4

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

ReaderWriterLockSlim

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

+0

Прохладная идея. Есть выборка? Не находить документацию на ReaderWriterSlimLock. Это то, что вы видели раньше или что-то, что вы только что провели мозговой штурм? –

+0

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

+0

Фактически, это почти работает, за исключением того, что FXcop справедливо указывает, что ReaderWriterLockSlim реализует IDisposable и должен располагаться вместе с остальными ресурсами объекта. Поэтому, когда вызывается dispose, я больше не смогу получить блокировку чтения, чтобы проверить, был ли объект удален или нет. –

3

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

+0

Да, но этот вопрос связан с тем, как с уверенностью бросать ObjectDisposedException в многопоточном сценарии. –

+0

@ Джейсон: в этом случае отредактируйте свой вопрос, чтобы сказать это. –

0

Учитывая, что «Disposed» boolean обновляется только в одном месте, и это ошибка в вашем вызывающем абоненте, чтобы использовать объект после вызова Disposed.

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

0

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

Смежные вопросы