2013-04-05 2 views
1
public class MyTask : IDisposable { ... } 

MyTask task = new MyTask(() => SomeTask); 

task.Completed += (s, e) => 
{ 
    // do something with result 
    ... 
    // dispose of this instance 
    ((MyTask)s).Dispose(); 
}; 

// execute the task 
task.Execute(); 

Очевидно, я не могу сказать, когда задача будет завершена, поэтому единственное фактическое место, которое я вижу, что я могу удалить этот экземпляр, находится в событии Completed.Безопасно ли вызывать Dispose на экземпляре из обработчика событий?

Безопасно ли это?

+0

Необходимо ли использовать экземпляры 'MyTask'? – asawyer

+0

ну, если бы не было необходимости, он бы не реализовал IDisposable. – Goran

+0

Прошу прощения, что так плохо сказано. Мне было просто любопытно, что вы делаете, что потребует ручного распоряжения, так как это довольно редкое требование. – asawyer

ответ

0

Существует, увы, нет общего правила относительно того, когда можно безопасно позвонить по номеру Dispose. Если Microsoft указала, что Dispose должно быть безопасно звонить в любое время, когда объект не используется, выполнение такого правила редко было бы затруднительным; в случаях, когда класс не всегда может выполнять всю необходимую очистку немедленно (*), обычно возможно установить флаг и/или иным образом организовать необходимую очистку, выполненную при следующей возможности. К сожалению, Microsoft не указывает, что реализации Dispose должны обрабатывать асинхронные запросы Dispose, а также нет общего способа для объекта, который содержит последнюю полезную ссылку на экземпляр IDisposable, чтобы запросить уведомление, когда было бы безопасно распоряжаться.

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

(*) Основная цель IDisposable - разрешить объекту уведомлять объекты, которые находятся за его пределами, но действуют от его имени в ущерб другим объектам, что они больше не должны этого делать (например, чтобы сообщить файловой системе, что он больше не должен предоставлять объекту эксклюзивный доступ к файлу]. Такие действия называются «освобождение ресурсов». Тот факт, что кто-то держит последнюю сохранившуюся ссылку на объект, может означать, что ни один другой поток не может использовать этот объект, но не подразумевает, что ни один другой поток не использует какие-либо потокобезопасные объекты, ресурсы которых необходимо освободить.

+0

Итак, все зависит от того, как была реализована утилизация. если реализация, где не оставить экземпляр в «нефункциональном» состоянии, не было бы вреда при вызове Dispose в обработчике событий? – Goran

+0

@Goran: Это зависит от конкретного объекта, о котором идет речь, но в целом, если владелец объекта намеревается сохранить его до тех пор, пока что-то не произойдет, и событие от объекта предоставляет уведомление, когда оно это делает, должно быть безопасно использовать это событие для удаления объекта. – supercat

+0

Я мог бы сделать сравнение с библиотекой задач. Вы создаете задачу, ее выполняете, и после завершения задачи вызывается метод, который передается ContinueWith. Можем ли мы реализовать оба объекта задачи (исходная задача и задача, возвращаемые ContinueWith) в этом методе? Я не хочу обсуждать, нужно ли распоряжаться Задачей (я знаю историю об утилизации WaitHandle), мне просто нужно знать - можем ли мы? – Goran

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