| @@ -23,6 +23,7 @@ · 22 unmodified lines |
| 23 | | 23 | |
| 24 | using System; | 24 | using System; |
| 25 | using System.Collections.Generic; | 25 | using System.Collections.Generic; |
| | 26 | using System.ComponentModel; |
| 26 | using GSF.Collections; | 27 | using GSF.Collections; |
| 27 | using GSF.Diagnostics; | 28 | using GSF.Diagnostics; |
| 28 | | 29 | |
| @@ -60,15 +61,16 @@ namespace GSF.Threading · 31 unmodified lines |
| 60 | /// Gets if this process is shutting down. | 61 | /// Gets if this process is shutting down. |
| 61 | /// </summary> | 62 | /// </summary> |
| 62 | public static bool IsShuttingDown { get; private set; } | 63 | public static bool IsShuttingDown { get; private set; } |
| | 64 | |
| 63 | /// <summary> | 65 | /// <summary> |
| 64 | /// Gets if this process has already shut down. | 66 | /// Gets if this process has already shut down. |
| 65 | /// </summary> | 67 | /// </summary> |
| 66 | public static bool HasShutdown { get; private set; } | 68 | public static bool HasShutdown { get; private set; } |
| 67 | | 69 | |
| 68 | private static List<WeakAction> s_onShutdownCallbackFirst; | 70 | private static readonly List<WeakAction> s_onShutdownCallbackFirst; |
| 69 | private static List<WeakAction> s_onShutdownCallbackDefault; | 71 | private static readonly List<WeakAction> s_onShutdownCallbackDefault; |
| 70 | private static List<WeakAction> s_onShutdownCallbackLast; | 72 | private static readonly List<WeakAction> s_onShutdownCallbackLast; |
| 71 | private static object s_syncRoot; | 73 | private static readonly object s_syncRoot; |
| 72 | | 74 | |
| 73 | static ShutdownHandler() | 75 | static ShutdownHandler() |
| 74 | { | 76 | { |
| @@ -128,6 +130,7 @@ namespace GSF.Threading · 53 unmodified lines |
| 128 | | 130 | |
| 129 | list.RemoveWhere(x => !x.IsAlive); | 131 | list.RemoveWhere(x => !x.IsAlive); |
| 130 | list.Add(new WeakAction(callback)); | 132 | list.Add(new WeakAction(callback)); |
| | 133 | |
| 131 | return true; | 134 | return true; |
| 132 | } | 135 | } |
| 133 | } | 136 | } |
| @@ -135,19 +138,19 @@ namespace GSF.Threading · 1 unmodified line |
| 135 | private static void InitiateSafeShutdown(object sender, EventArgs e) | 138 | private static void InitiateSafeShutdown(object sender, EventArgs e) |
| 136 | { | 139 | { |
| 137 | List<WeakAction> shutdownList = new List<WeakAction>(); | 140 | List<WeakAction> shutdownList = new List<WeakAction>(); |
| | 141 | |
| 138 | lock (s_syncRoot) | 142 | lock (s_syncRoot) |
| 139 | { | 143 | { |
| 140 | if (IsShuttingDown) | 144 | if (IsShuttingDown) |
| 141 | { | | |
| 142 | return; | 145 | return; |
| 143 | } | 146 | |
| 144 | IsShuttingDown = true; | 147 | IsShuttingDown = true; |
| 145 | shutdownList.AddRange(s_onShutdownCallbackFirst); | 148 | shutdownList.AddRange(s_onShutdownCallbackFirst); |
| 146 | shutdownList.AddRange(s_onShutdownCallbackDefault); | 149 | shutdownList.AddRange(s_onShutdownCallbackDefault); |
| 147 | shutdownList.AddRange(s_onShutdownCallbackLast); | 150 | shutdownList.AddRange(s_onShutdownCallbackLast); |
| 148 | } | 151 | } |
| 149 | | 152 | |
| 150 | foreach (var weakAction in shutdownList) | 153 | foreach (WeakAction weakAction in shutdownList) |
| 151 | { | 154 | { |
| 152 | try | 155 | try |
| 153 | { | 156 | { |
| @@ -160,22 +163,22 @@ namespace GSF.Threading · 6 unmodified lines |
| 160 | } | 163 | } |
| 161 | | 164 | |
| 162 | Logger.Shutdown(); | 165 | Logger.Shutdown(); |
| | 166 | |
| 163 | HasShutdown = true; | 167 | HasShutdown = true; |
| 164 | } | 168 | } |
| 165 | | 169 | |
| 166 | /// <summary> | 170 | /// <summary> |
| 167 | /// Requests that certain components initiate a safe shutdown. This method | 171 | /// Requests that certain components initiate a safe shutdown. |
| 168 | /// should only be called when the main thread exits. Calling this outside | | |
| 169 | /// of the application exiting could result in unpredictable behavior. | | |
| 170 | /// </summary> | 172 | /// </summary> |
| 171 | /// <param name="areYouSure">To ensure proper use, specify this value as a constant. 'OnlyCallThisWhenMainExits'</param> | 173 | /// <remarks> |
| 172 | public static void InitiateSafeShutdown(string areYouSure) | 174 | /// This method should only be called when the main thread exits. Calling this outside |
| | 175 | /// of the application exiting could result in unpredictable behavior. |
| | 176 | /// </remarks> |
| | 177 | #if !SQLCLR |
| | 178 | [EditorBrowsable(EditorBrowsableState.Advanced)] |
| | 179 | #endif |
| | 180 | public static void InitiateSafeShutdown() |
| 173 | { | 181 | { |
| 174 | if (areYouSure != "OnlyCallThisWhenMainExits") | | |
| 175 | { | | |
| 176 | throw new InvalidOperationException("This method must only be called when the main thread exits."); | | |
| 177 | } | | |
| 178 | | | |
| 179 | InitiateSafeShutdown(null, null); | 182 | InitiateSafeShutdown(null, null); |
| 180 | } | 183 | } |
| 181 | } | 184 | } |