| @@ -1,9 +1,7 | |||||
| 1 | using Implab.Diagnostics; |
|
1 | using Implab.Diagnostics; | |
| 2 | using System; |
|
2 | using System; | |
| 3 |
using System. |
|
3 | using System.Threading; | |
| 4 |
using System. |
|
4 | using System.IO; | |
| 5 | using System.Linq; |
|
|||
| 6 | using System.Web; |
|
|||
| 7 |
|
5 | |||
| 8 | namespace Implab { |
|
6 | namespace Implab { | |
| 9 | /// <summary> |
|
7 | /// <summary> | |
| @@ -11,40 +9,84 namespace Implab { | |||||
| 11 | /// </summary> |
|
9 | /// </summary> | |
| 12 | public class Disposable : IDisposable { |
|
10 | public class Disposable : IDisposable { | |
| 13 |
|
11 | |||
| 14 |
|
|
12 | int m_disposed; | |
| 15 |
|
13 | |||
| 16 | public event EventHandler Disposed; |
|
14 | public event EventHandler Disposed; | |
| 17 |
|
15 | |||
| 18 | public bool IsDisposed { |
|
16 | public bool IsDisposed { | |
| 19 |
get { |
|
17 | get { | |
|
|
18 | Thread.MemoryBarrier(); | |||
|
|
19 | return m_disposed != 0; | |||
|
|
20 | } | |||
| 20 | } |
|
21 | } | |
| 21 |
|
22 | |||
|
|
23 | /// <summary> | |||
|
|
24 | /// Asserts the object is not disposed. | |||
|
|
25 | /// </summary> | |||
|
|
26 | /// <exception cref="ObjectDisposedException">The object is disposed</exception> | |||
|
|
27 | /// <remarks> | |||
|
|
28 | /// Успешная проверка того, что объект не освобожден еще не гарантирует, что он не | |||
|
|
29 | /// будет освобожден сразу после нее, поэтому методы использующие проверку должны | |||
|
|
30 | /// учитывать, что объект может быть освобожден из параллельного потока. | |||
|
|
31 | /// Данны метод служит для упрощения отладки ошибок при использовании объекта после его | |||
|
|
32 | /// освобождения. | |||
|
|
33 | /// </remarks> | |||
|
|
34 | /// <example> | |||
|
|
35 | /// // пример синхронизированного освобождения ресурсов | |||
|
|
36 | /// class FileStore : Disposable { | |||
|
|
37 | /// readonly TextWriter m_file; | |||
|
|
38 | /// readonly obejct m_sync = new object(); | |||
|
|
39 | /// | |||
|
|
40 | /// public FileStore(string file) { | |||
|
|
41 | /// m_file = new TextWriter(File.OpenWrite(file)); | |||
|
|
42 | /// } | |||
|
|
43 | /// | |||
|
|
44 | /// public void Write(string text) { | |||
|
|
45 | /// lock(m_sync) { | |||
|
|
46 | /// AssertNotDisposed(); | |||
|
|
47 | /// m_file.Write(text); | |||
|
|
48 | /// } | |||
|
|
49 | /// } | |||
|
|
50 | /// | |||
|
|
51 | /// protected override void Dispose(bool disposing) { | |||
|
|
52 | /// if (disposing) | |||
|
|
53 | /// lock(m_sync) { | |||
|
|
54 | /// m_file.Dipose(); | |||
|
|
55 | /// base.Dispose(true); | |||
|
|
56 | /// } | |||
|
|
57 | /// else | |||
|
|
58 | /// base.Dispose(false); | |||
|
|
59 | /// } | |||
|
|
60 | /// } | |||
|
|
61 | /// <example> | |||
| 22 | protected void AssertNotDisposed() { |
|
62 | protected void AssertNotDisposed() { | |
| 23 | if (m_disposed) |
|
63 | Thread.MemoryBarrier(); | |
| 24 | throw new ObjectDisposedException(this.ToString()); |
|
64 | if (m_disposed != 0) | |
|
|
65 | throw new ObjectDisposedException(ToString()); | |||
| 25 | } |
|
66 | } | |
| 26 | /// <summary> |
|
67 | /// <summary> | |
| 27 |
/// |
|
68 | /// Вызывает событие <see cref="Disposed"/> | |
| 28 | /// </summary> |
|
69 | /// </summary> | |
| 29 | /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод |
|
70 | /// <param name="disposing">Признак того, что нужно освободить ресурсы, иначе данный метод | |
| 30 | /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого |
|
71 | /// вызван сборщиком мусора и нужно освобождать ТОЛЬКО неуправляемые ресурсы ТОЛЬКО этого | |
| 31 | /// объекта.</param> |
|
72 | /// объекта.</param> | |
| 32 | /// <remarks> |
|
73 | /// <remarks> | |
| 33 | /// Данный метод осуществляет проверку того, что объект уже был освобожден, чтобы не вызывать |
|
74 | /// Данный метод вызывается гарантированно один раз даже при одновременном вызове <see cref="Dispose()"/> | |
| 34 | /// событие <see cref="Disposed"/>. Не поддерживает многопоточность. |
|
75 | /// из нескольких потоков. | |
| 35 | /// </remarks> |
|
76 | /// </remarks> | |
| 36 | protected virtual void Dispose(bool disposing) { |
|
77 | protected virtual void Dispose(bool disposing) { | |
| 37 |
if (disposing |
|
78 | if (disposing) { | |
| 38 | m_disposed = true; |
|
|||
| 39 |
|
||||
| 40 | EventHandler temp = Disposed; |
|
79 | EventHandler temp = Disposed; | |
| 41 |
if (temp != null) |
|
80 | if (temp != null) | |
| 42 | temp(this,EventArgs.Empty); |
|
81 | temp(this, EventArgs.Empty); | |
| 43 | } |
|
82 | } | |
| 44 | } |
|
83 | } | |
|
|
84 | ||||
| 45 | public void Dispose() { |
|
85 | public void Dispose() { | |
| 46 | Dispose(true); |
|
86 | if (Interlocked.Increment(ref m_disposed) == 1) { | |
| 47 | GC.SuppressFinalize(this); |
|
87 | Dispose(true); | |
|
|
88 | GC.SuppressFinalize(this); | |||
|
|
89 | } | |||
| 48 | } |
|
90 | } | |
| 49 |
|
91 | |||
| 50 | /// <summary> |
|
92 | /// <summary> | |
General Comments 0
You need to be logged in to leave comments.
Login now
