Как узнать, что объект утилизировал?
У меня есть многопоточное приложение, и CancellationToken
используется в качестве общего объекта. Каждый поток может вызвать его, чтобы сообщить другим потокам, что задание отменено. Затем один поток выполняет очистку и распределяет каждый объект следующим образом CancellationToken
. Затем, если поток пытается использовать его, возникает исключение:
CancellationTokenSource был удален.
Как я могу узнать, что объект расположен, прежде чем использовать его?
4 ответа:
Ну, согласно Reflector,
CancellationTokenSource
имеет внутренний методIsDisposed
, который мог бы вам сказать, но поскольку он внутренний, вы не должны его вызывать.В любом случае, если один поток выдергивает структуры данных и объекты, от которых зависят другие потоки, то не делайте этого. Исправьте свой код и оставьте эти объекты жить на время их потребности.
Другими словами, дождитесь, пока другие потоки закончат нуждаться вCancellationTokenSource
, прежде чем избавиться от него.
Правильнее было бы для создателей некоторых одноразовых объектов пойти немного против "правила" Microsoft, что выполнение любого действия над удаленным объектом должно вызвать исключение, и вместо этого следовать более общему правилу, что исключение должно быть вызвано в любое время, когда постусловия метода не могут быть выполнены. Если цель метода отмены состоит в том, чтобы гарантировать, что никто не будет продолжать рассматривать работу как живую, и даже до того, как метод отмены будет вызван, все считают задание как мертвое, то постусловие для метода выполняется независимо от того, удален ли объект.
Как правило, код вне хорошо спроектированного объекта не должен запрашивать, был ли он удален, за исключением, возможно, утверждения, что он был удален. Вместо этого сам объект должен предоставлять методы, значение которых для удаленного объекта было бы ясным и недвусмысленным. Эти методы могли бы внутренне использовать флаг IsDisposed, но должны были бы использовать любую блокировку необходимо предотвратить условия гонки. В общем, паттерн
if (!myThing.isDisposed) myThing.DoSomething();- это указание на то, что myThing действительно должен поддерживать метод DoSomethingIfNotDisposed (возможно, называемый TryDoSomething). Если вы не можете этого сделать, я склоняюсь к тому, чтобы написать свой собственный метод расширения DoSomethingIfNotDisposed и использовать Try/Catch, чтобы подавить исключение ObjectDisposedException (или любое другое конкретное исключение, которое вызовет объект).
Перед использованием объекта убедитесь, что он удален.
Все еще не лучший шаблон дизайна. однако вот то, что я использую, действительно определяет, расположен ли объект.
if (!object.IsDisposed) object.DoSomething();
Или
public string DoSomething() { if (this.IsDisposed) return null; }
Если это не работает, вы можете попробовать добавить флаг IsDisposed и переопределить метод dispose. И установите это значение true в своем собственном коде.