Disposable.cs
102 lines
| 4.3 KiB
| text/x-csharp
|
CSharpLexer
cin
|
r152 | using Implab.Diagnostics; | |
using System; | |||
cin
|
r208 | using System.Diagnostics.CodeAnalysis; | |
cin
|
r152 | using System.Threading; | |
namespace Implab.Components { | |||
/// <summary> | |||
/// Base class the objects which support disposing. | |||
/// </summary> | |||
public class Disposable : IDisposable { | |||
cin
|
r213 | ||
cin
|
r152 | int m_disposed; | |
public event EventHandler Disposed; | |||
public bool IsDisposed { | |||
get { | |||
Thread.MemoryBarrier(); | |||
return m_disposed != 0; | |||
} | |||
} | |||
/// <summary> | |||
/// Asserts the object is not disposed. | |||
/// </summary> | |||
/// <exception cref="ObjectDisposedException">The object is disposed</exception> | |||
/// <remarks> | |||
/// Успешная проверка того, что объект не освобожден еще не гарантирует, что он не | |||
/// будет освобожден сразу после нее, поэтому методы использующие проверку должны | |||
/// учитывать, что объект может быть освобожден из параллельного потока. | |||
/// Данны метод служит для упрощения отладки ошибок при использовании объекта после его | |||
/// освобождения. | |||
/// </remarks> | |||
/// <example> | |||
/// // пример синхронизированного освобождения ресурсов | |||
/// class FileStore : Disposable { | |||
/// readonly TextWriter m_file; | |||
/// readonly obejct m_sync = new object(); | |||
/// | |||
/// public FileStore(string file) { | |||
/// m_file = new TextWriter(File.OpenWrite(file)); | |||
/// } | |||
/// | |||
/// public void Write(string text) { | |||
/// lock(m_sync) { | |||
/// AssertNotDisposed(); | |||
/// m_file.Write(text); | |||
/// } | |||
/// } | |||
/// | |||
/// protected override void Dispose(bool disposing) { | |||
/// if (disposing) | |||
/// lock(m_sync) { | |||
/// m_file.Dipose(); | |||
/// base.Dispose(true); | |||
/// } | |||
/// else | |||
/// base.Dispose(false); | |||
/// } | |||
/// } | |||
/// <example> | |||
protected void AssertNotDisposed() { | |||
Thread.MemoryBarrier(); | |||
if (m_disposed != 0) | |||
throw new ObjectDisposedException(ToString()); | |||
} | |||
/// <summary> | |||
/// Вызывает событие <see cref="Disposed"/> | |||
/// </summary> | |||
/// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод | |||
/// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого | |||
/// объекта.</param> | |||
/// <remarks> | |||
/// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> | |||
/// из нескольких потоков. | |||
/// </remarks> | |||
protected virtual void Dispose(bool disposing) { | |||
cin
|
r213 | if (disposing) | |
Disposed.DispatchEvent(this, EventArgs.Empty); | |||
cin
|
r152 | } | |
cin
|
r208 | [SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly", Justification = "Dipose(bool) and GC.SuppessFinalize are called")] | |
cin
|
r152 | public void Dispose() { | |
if (Interlocked.Increment(ref m_disposed) == 1) { | |||
Dispose(true); | |||
GC.SuppressFinalize(this); | |||
} | |||
} | |||
/// <summary> | |||
/// Записывает сообщение об утечке объекта. | |||
/// </summary> | |||
protected virtual void ReportObjectLeaks() { | |||
TraceLog.TraceWarning("The object is marked as disposable but isn't disposed properly: {0}", this); | |||
} | |||
~Disposable() { | |||
Dispose(false); | |||
ReportObjectLeaks(); | |||
} | |||
} | |||
} |