Как узнать, что объект утилизирован? - PullRequest
6 голосов
/ 14 апреля 2011

У меня многопоточное приложение, а CancellationToken используется как общий объект.Каждый поток может запустить его, чтобы сообщить другим потокам, что задание отменено.Затем один поток выполняет очистку и удаляет каждый объект, подобный этому CancellationToken.Затем, если поток пытается использовать его, возникает исключение:

Объект CancellationTokenSource был удален.

Как узнать, что объект удален перед его использованием

Ответы [ 4 ]

4 голосов
/ 14 апреля 2011

Ну, согласно Reflector, CancellationTokenSource имеет внутренний IsDisposed метод, который мог бы вам сказать, но поскольку он внутренний, вы не должны вызывать его.

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

Другими словами, дождитесь, пока другим потокам не понадобится CancellationTokenSource, прежде чем избавиться от него.

2 голосов
/ 14 апреля 2011

Правильный порядок действий будет означать, что создатели некоторых Одноразовых объектов будут слегка противоречить «правилу» Microsoft о том, что выполнение любого действия с удаленным объектом должно вызывать исключение, а вместо этого следовать более общему правилу, согласно которому исключение должно быть выбрасывается в любое время, когда условия метода не могут быть выполнены. Если цель метода Cancel состоит в том, чтобы гарантировать, что никто не будет продолжать рассматривать работу как живую, и даже до вызова метода Cancel все считают работу мертвой, то пост-условие для метода выполняется независимо от того, расположен ли объект.

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

  if (!myThing.isDisposed) 
    myThing.DoSomething();

указывает на то, что myThing действительно должен поддерживать метод DoSomethingIfNotDisposed (возможно, называется TryDoSomething). Если вы не можете этого сделать, я склонен написать собственный метод расширения DoSomethingIfNotDisposed и использовать Try / Catch для подавления исключения ObjectDisposedException (или любого конкретного исключения, которое будет выдавать объект).

1 голос
/ 14 апреля 2011

проверьте, находится ли объект перед его использованием.

Все еще не лучший шаблон дизайна. однако вот что я использую, чтобы определить, расположен ли объект.

if (!object.IsDisposed) object.DoSomething();

или

public string DoSomething()
{
    if (this.IsDisposed) return null;
}

Если это не работает, вы можете попробовать добавить флаг IsDisposed и переопределить метод dispose. И установите это значение в свой собственный код.

0 голосов
/ 02 ноября 2017

Наследуй свой класс и добавь свойство:

class MyCancellationTokenSource: CancellationTokenSource
{
    public bool MyIsDisposed { get; private set; }
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        MyIsDisposed = true;
     }
}
...