2016-01-22 10 views
1

Я заметил, что некоторые классы на MSDN (like this one), которые имеют Disposing событие со следующим комментарием:Можете ли вы запустить событие «Disposing», если Dispose() вызывается финализатором?

Происходит при Dispose вызывается или, когда этот объект будет завершен и собраны сборщиком мусора.

Я хочу реализовать свое собственное событие Disposing в моем классе. Вот моя основная реализация (following the best practices for the dispose pattern):

public abstract class Handle : IDisposable 
{ 
    public bool Disposed { get; private set; } 

    public event System.Action DisposingCompleted; 

    public Handle() 
    { 
     Disposed = false; 
    } 

    ~Handle() 
    { 
     Dispose(false); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing = false) 
    { 
     if (Disposed) 
     { 
      return; 
     } 

     if (disposing) 
     { 
      HandleManagedResources(); 
     } 

     HandleUnManagedResources(); 

     Disposed = true; 

     if (DisposingCompleted != null) 
     { 
      DisposingCompleted(); 
     } 
    } 

    protected virtual void HandleManagedResources() {} 
    protected virtual void HandleUnManagedResources() {} 
} 

Кто-то упомянул о моем обзоре кода, что они не уверены в том или не стрелять безопасно событие, как это потому, что Dispose() может вызываться из финализации, но, в соответствии с комментарии к этой ссылке MSDN, которую я добавил наверху, ясно, что есть объекты, запускающие события, когда они выбраны или завершены.

Я что-то упустил или это безопасно? Как GraphicsDevice реализовать событие, которое уволено из распоряжения ИЛИ при завершении? Если ответ просто «Нет, вы не можете этого делать никогда», тогда есть ли другой способ достижения такого же эффекта? (Событие для объекта расположены ИЛИ завершена)

+0

Вы должны использовать стандартную предлагаемую реализацию и шаблон, например, именования и условные обозначения, вместо того, чтобы кататься самостоятельно. В частности, вы должны использовать 'bool disposing' вместо' bool fromFinalizer'. –

+0

@ LasseV.Karlsen Конечно, я изменил имена вокруг. – Foggzie

+0

Возможно, вы захотите прочитать сообщение Эрика Липперса о всех странностях, которые могут произойти в финализаторах. Http://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/ – juharr

ответ

2

Если вы собираетесь сделать что-нибудь с участием других объектов в Dispose методы, которые вы должны делать это только когда Dispose называется явно не тогда, когда она вызывается из финализации.

Причина этого в том, что, если этот другой объект также имеет право на сбор, у вас нет гарантии, что этот объект еще не был доработан.

+0

Итак, как происходит что-то вроде связанного с GraphicsDevice, связанного с событием, которое, по его словам, срабатывает, когда вызывается Dispose или когда этот объект завершен? Что, если я могу гарантировать, что подписчики будут жить дольше, чем издатели? – Foggzie

+1

Вы можете легко написать код, чтобы сделать это, но это не рекомендуется и не обязательно безопасно делать. –

+0

Так что я смущен тем, как это реализовано классами Microsoft. Мне трудно поверить, что функциональность, встроенная в инфраструктуру XNA, например, «GraphicsDevice» и «StorageContainer», удалось сделать так, но нигде не заметили, что эти события небезопасны в использовании. Если ответ просто «Нет, вы не можете этого делать никогда», тогда есть ли другой способ достижения такого же эффекта? – Foggzie

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

  • Нет связанных вопросов^_^