Showing the changes to Source/Libraries/GSF.ServiceProcess/ServiceProcess.cs (1 of 628 files). Show all
Unified · Split
| @@ -0,0 +1,400 @@ | |||
| 1 | //****************************************************************************************************** | ||
| 2 | // ServiceProcess.cs - Gbtc | ||
| 3 | // | ||
| 4 | // Copyright � 2010, Grid Protection Alliance. All Rights Reserved. | ||
| 5 | // | ||
| 6 | // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See | ||
| 7 | // the NOTICE file distributed with this work for additional information regarding copyright ownership. | ||
| 8 | // The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may | ||
| 9 | // not use this file except in compliance with the License. You may obtain a copy of the License at: | ||
| 10 | // | ||
| 11 | // http://www.opensource.org/licenses/eclipse-1.0.php | ||
| 12 | // | ||
| 13 | // Unless agreed to in writing, the subject software distributed under the License is distributed on an | ||
| 14 | // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the | ||
| 15 | // License for the specific language governing permissions and limitations. | ||
| 16 | // | ||
| 17 | // Code Modification History: | ||
| 18 | // ---------------------------------------------------------------------------------------------------- | ||
| 19 | // 09/13/2006 - Pinal C. Patel | ||
| 20 | // Generated original version of source code. | ||
| 21 | // 09/30/2008 - J. Ritchie Carroll | ||
| 22 | // Converted to C#. | ||
| 23 | // 03/03/2009 - Pinal C. Patel | ||
| 24 | // Edited code comments. | ||
| 25 | // 09/14/2009 - Stephen C. Wills | ||
| 26 | // Added new header and license agreement. | ||
| 27 | // 10/8/2012 - Danyelle Gilliam | ||
| 28 | // Modified Header | ||
| 29 | // | ||
| 30 | //****************************************************************************************************** | ||
| 31 | |||
| 32 | |||
| 33 | |||
| 34 | using GSF.Units; | ||
| 35 | using System; | ||
| 36 | using System.Text; | ||
| 37 | using System.Threading; | ||
| 38 | |||
| 39 | namespace GSF.ServiceProcess | ||
| 40 | { | ||
| 41 | #region [ Enumerations ] | ||
| 42 | |||
| 43 | /// <summary> | ||
| 44 | /// Indicates the current state of <see cref="ServiceProcess"/>. | ||
| 45 | /// </summary> | ||
| 46 | public enum ServiceProcessState | ||
| 47 | { | ||
| 48 | /// <summary> | ||
| 49 | /// <see cref="ServiceProcess"/> has not been started. | ||
| 50 | /// </summary> | ||
| 51 | Unprocessed, | ||
| 52 | /// <summary> | ||
| 53 | /// <see cref="ServiceProcess"/> is currently executing. | ||
| 54 | /// </summary> | ||
| 55 | Processing, | ||
| 56 | /// <summary> | ||
| 57 | /// <see cref="ServiceProcess"/> has completed processing. | ||
| 58 | /// </summary> | ||
| 59 | Processed, | ||
| 60 | /// <summary> | ||
| 61 | /// <see cref="ServiceProcess"/> was aborted. | ||
| 62 | /// </summary> | ||
| 63 | Aborted, | ||
| 64 | /// <summary> | ||
| 65 | /// <see cref="ServiceProcess"/> stopped due to exception. | ||
| 66 | /// </summary> | ||
| 67 | Exception | ||
| 68 | } | ||
| 69 | |||
| 70 | #endregion | ||
| 71 | |||
| 72 | /// <summary> | ||
| 73 | /// Represents a process that executes asynchronously inside a <see cref="ServiceHelper"/>. | ||
| 74 | /// </summary> | ||
| 75 | /// <seealso cref="ServiceHelper"/> | ||
| 76 | public class ServiceProcess : IDisposable, IProvideStatus | ||
| 77 | { | ||
| 78 | #region [ Members ] | ||
| 79 | |||
| 80 | //Events | ||
| 81 | |||
| 82 | /// <summary> | ||
| 83 | /// Occurs when the <see cref="CurrentState"/> of the <see cref="ServiceProcess"/> changes. | ||
| 84 | /// </summary> | ||
| 85 | public event EventHandler StateChanged; | ||
| 86 | |||
| 87 | // Fields | ||
| 88 | #if ThreadTracking | ||
| 89 | private ManagedThread m_processThread; | ||
| 90 | #else | ||
| 91 | private Thread m_processThread; | ||
| 92 | #endif | ||
| 93 | private string m_name; | ||
| 94 | private object[] m_arguments; | ||
| 95 | private Action<string, object[]> m_executionMethod; | ||
| 96 | private ServiceProcessState m_currentState; | ||
| 97 | private DateTime m_executionStartTime; | ||
| 98 | private DateTime m_executionStopTime; | ||
| 99 | private bool m_disposed; | ||
| 100 | |||
| 101 | #endregion | ||
| 102 | |||
| 103 | #region [ Constructors ] | ||
| 104 | |||
| 105 | /// <summary> | ||
| 106 | /// Initializes a new instance of the <see cref="ServiceProcess"/> class. | ||
| 107 | /// </summary> | ||
| 108 | /// <param name="executionMethod"><see cref="Delegate"/> that gets invoked when <see cref="Start()"/> is called.</param> | ||
| 109 | /// <param name="name">Name of the <see cref="ServiceProcess"/>.</param> | ||
| 110 | /// <param name="arguments">Arguments to be passed in to the <paramref name="executionMethod"/>.</param> | ||
| 111 | public ServiceProcess(Action<string, object[]> executionMethod, string name, params object[] arguments) | ||
| 112 | { | ||
| 113 | m_name = name; | ||
| 114 | m_arguments = arguments; | ||
| 115 | m_executionMethod = executionMethod; | ||
| 116 | m_currentState = ServiceProcessState.Unprocessed; | ||
| 117 | } | ||
| 118 | |||
| 119 | /// <summary> | ||
| 120 | /// Releases the unmanaged resources before the <see cref="ServiceProcess" /> object is reclaimed by <see cref="GC"/>. | ||
| 121 | /// </summary> | ||
| 122 | ~ServiceProcess() | ||
| 123 | { | ||
| 124 | Dispose(false); | ||
| 125 | } | ||
| 126 | |||
| 127 | #endregion | ||
| 128 | |||
| 129 | #region [ Properties ] | ||
| 130 | |||
| 131 | /// <summary> | ||
| 132 | /// Gets or sets the name of the <see cref="ServiceProcess"/>. | ||
| 133 | /// </summary> | ||
| 134 | /// <exception cref="ArgumentNullException">The value being assigned is a null or empty string.</exception> | ||
| 135 | public string Name | ||
| 136 | { | ||
| 137 | get | ||
| 138 | { | ||
| 139 | return m_name; | ||
| 140 | } | ||
| 141 | set | ||
| 142 | { | ||
| 143 | if (string.IsNullOrEmpty(value)) | ||
| 144 | throw new ArgumentNullException("Name"); | ||
| 145 | |||
| 146 | m_name = value; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | /// <summary> | ||
| 151 | /// Gets or sets the arguments to be passed in to the <see cref="ExecutionMethod"/>. | ||
| 152 | /// </summary> | ||
| 153 | public object[] Arguments | ||
| 154 | { | ||
| 155 | get | ||
| 156 | { | ||
| 157 | return m_arguments; | ||
| 158 | } | ||
| 159 | set | ||
| 160 | { | ||
| 161 | m_arguments = value; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | /// <summary> | ||
| 166 | /// Gets or sets the <see cref="Delegate"/> that gets invoked when <see cref="Start()"/> is called. | ||
| 167 | /// </summary> | ||
| 168 | /// <remarks> | ||
| 169 | /// Argument1 gets the <see cref="Name"/> of the <see cref="ServiceProcess"/>.<br/> | ||
| 170 | /// Argument2 gets the <see cref="Arguments"/> of the <see cref="ServiceProcess"/>. | ||
| 171 | /// </remarks> | ||
| 172 | public Action<string, object[]> ExecutionMethod | ||
| 173 | { | ||
| 174 | get | ||
| 175 | { | ||
| 176 | return m_executionMethod; | ||
| 177 | } | ||
| 178 | set | ||
| 179 | { | ||
| 180 | m_executionMethod = value; | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | /// <summary> | ||
| 185 | /// Gets the current <see cref="ServiceProcessState"/>. | ||
| 186 | /// </summary> | ||
| 187 | public ServiceProcessState CurrentState | ||
| 188 | { | ||
| 189 | get | ||
| 190 | { | ||
| 191 | return m_currentState; | ||
| 192 | } | ||
| 193 | private set | ||
| 194 | { | ||
| 195 | m_currentState = value; | ||
| 196 | OnStateChanged(); // Notify of the change in state. | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | /// <summary> | ||
| 201 | /// Gets the <see cref="DateTime"/> when execution of <see cref="ServiceProcess"/> last started. | ||
| 202 | /// </summary> | ||
| 203 | public DateTime ExecutionStartTime | ||
| 204 | { | ||
| 205 | get | ||
| 206 | { | ||
| 207 | return m_executionStartTime; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | /// <summary> | ||
| 212 | /// Gets the <see cref="DateTime"/> when execution of <see cref="ServiceProcess"/> last completed. | ||
| 213 | /// </summary> | ||
| 214 | public DateTime ExecutionStopTime | ||
| 215 | { | ||
| 216 | get | ||
| 217 | { | ||
| 218 | return m_executionStopTime; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | /// <summary> | ||
| 223 | /// Gets the <see cref="Time"/> taken by the <see cref="ServiceProcess"/> during the last execution. | ||
| 224 | /// </summary> | ||
| 225 | public Time LastExecutionTime | ||
| 226 | { | ||
| 227 | get | ||
| 228 | { | ||
| 229 | return Ticks.ToSeconds(m_executionStopTime.Ticks - m_executionStartTime.Ticks); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | /// <summary> | ||
| 234 | /// Gets the descriptive status of the <see cref="ServiceProcess"/>. | ||
| 235 | /// </summary> | ||
| 236 | public string Status | ||
| 237 | { | ||
| 238 | get | ||
| 239 | { | ||
| 240 | StringBuilder status = new StringBuilder(); | ||
| 241 | |||
| 242 | status.Append(" Process Name: "); | ||
| 243 | status.Append(m_name); | ||
| 244 | status.AppendLine(); | ||
| 245 | status.Append(" Current State: "); | ||
| 246 | status.Append(m_currentState.ToString()); | ||
| 247 | status.AppendLine(); | ||
| 248 | status.Append(" Execution Start Time: "); | ||
| 249 | |||
| 250 | if (m_executionStartTime != DateTime.MinValue) | ||
| 251 | { | ||
| 252 | status.Append(m_executionStartTime.ToString()); | ||
| 253 | } | ||
| 254 | else | ||
| 255 | { | ||
| 256 | status.Append("N/A"); | ||
| 257 | } | ||
| 258 | |||
| 259 | status.AppendLine(); | ||
| 260 | status.Append(" Execution Stop Time: "); | ||
| 261 | |||
| 262 | if (m_executionStopTime != DateTime.MinValue) | ||
| 263 | { | ||
| 264 | status.Append(m_executionStopTime.ToString()); | ||
| 265 | } | ||
| 266 | else | ||
| 267 | { | ||
| 268 | status.Append("N/A"); | ||
| 269 | } | ||
| 270 | |||
| 271 | status.AppendLine(); | ||
| 272 | status.Append(" Last Execution Time: "); | ||
| 273 | status.Append(LastExecutionTime.ToString()); | ||
| 274 | status.AppendLine(); | ||
| 275 | |||
| 276 | return status.ToString(); | ||
| 277 | } | ||
| 278 | } | ||
| 279 | |||
| 280 | #endregion | ||
| 281 | |||
| 282 | #region [ Methods ] | ||
| 283 | |||
| 284 | /// <summary> | ||
| 285 | /// Starts the execution of <see cref="ServiceProcess"/>. | ||
| 286 | /// </summary> | ||
| 287 | public void Start() | ||
| 288 | { | ||
| 289 | Start(m_arguments); | ||
| 290 | } | ||
| 291 | |||
| 292 | /// <summary> | ||
| 293 | /// Starts the execution of <see cref="ServiceProcess"/>. | ||
| 294 | /// </summary> | ||
| 295 | /// <param name="arguments">Arguments to be passed in to the <see cref="ExecutionMethod"/>.</param> | ||
| 296 | public void Start(object[] arguments) | ||
| 297 | { | ||
| 298 | // Start the execution on a seperate thread. | ||
| 299 | #if ThreadTracking | ||
| 300 | m_processThread = new ManagedThread(InvokeExecutionMethod); | ||
| 301 | m_processThread.Name = "TVA.ServiceProcess.ServiceProcess.InvokeExecutionMethod() [" + m_name + "]"; | ||
| 302 | #else | ||
| 303 | m_processThread = new Thread(InvokeExecutionMethod); | ||
| 304 | #endif | ||
| 305 | m_processThread.Start(arguments); | ||
| 306 | } | ||
| 307 | |||
| 308 | /// <summary> | ||
| 309 | /// Stops the execution of <see cref="ServiceProcess"/> if it executing. | ||
| 310 | /// </summary> | ||
| 311 | public void Abort() | ||
| 312 | { | ||
| 313 | // We'll abort the process only if it is currently executing. | ||
| 314 | if (m_processThread != null) | ||
| 315 | { | ||
| 316 | if (m_processThread.IsAlive) | ||
| 317 | m_processThread.Abort(); | ||
| 318 | } | ||
| 319 | m_processThread = null; | ||
| 320 | } | ||
| 321 | |||
| 322 | /// <summary> | ||
| 323 | /// Releases all the resources used by the <see cref="ServiceProcess"/> object. | ||
| 324 | /// </summary> | ||
| 325 | public void Dispose() | ||
| 326 | { | ||
| 327 | Dispose(true); | ||
| 328 | GC.SuppressFinalize(this); | ||
| 329 | } | ||
| 330 | |||
| 331 | /// <summary> | ||
| 332 | /// Releases the unmanaged resources used by the <see cref="ServiceProcess"/> and optionally releases the managed resources. | ||
| 333 | /// </summary> | ||
| 334 | /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param> | ||
| 335 | protected virtual void Dispose(bool disposing) | ||
| 336 | { | ||
| 337 | if (!m_disposed) | ||
| 338 | { | ||
| 339 | try | ||
| 340 | { | ||
| 341 | // This will be done regardless of whether the object is finalized or disposed. | ||
| 342 | Abort(); | ||
| 343 | if (disposing) | ||
| 344 | { | ||
| 345 | // This will be done only when the object is disposed by calling Dispose(). | ||
| 346 | m_executionMethod = null; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | finally | ||
| 350 | { | ||
| 351 | m_disposed = true; // Prevent duplicate dispose. | ||
| 352 | } | ||
| 353 | } | ||
| 354 | } | ||
| 355 | |||
| 356 | /// <summary> | ||
| 357 | /// Raises the <see cref="StateChanged"/> event. | ||
| 358 | /// </summary> | ||
| 359 | protected virtual void OnStateChanged() | ||
| 360 | { | ||
| 361 | if (StateChanged != null) | ||
| 362 | StateChanged(this, EventArgs.Empty); | ||
| 363 | } | ||
| 364 | |||
| 365 | private void InvokeExecutionMethod(object state) | ||
| 366 | { | ||
| 367 | if (m_executionMethod != null) | ||
| 368 | { | ||
| 369 | CurrentState = ServiceProcessState.Processing; | ||
| 370 | m_executionStartTime = DateTime.Now; | ||
| 371 | m_executionStopTime = DateTime.MinValue; | ||
| 372 | |||
| 373 | try | ||
| 374 | { | ||
| 375 | // We'll keep the invocation of the delegate in Try...Catch to absorb any exceptions that | ||
| 376 | // were not handled by the consumer. | ||
| 377 | m_executionMethod(m_name, state as object[]); | ||
| 378 | |||
| 379 | CurrentState = ServiceProcessState.Processed; | ||
| 380 | } | ||
| 381 | catch (ThreadAbortException) | ||
| 382 | { | ||
| 383 | CurrentState = ServiceProcessState.Aborted; | ||
| 384 | } | ||
| 385 | catch (Exception) | ||
| 386 | { | ||
| 387 | // We'll absorb any exceptions if unhandled by the client. | ||
| 388 | CurrentState = ServiceProcessState.Exception; | ||
| 389 | } | ||
| 390 | finally | ||
| 391 | { | ||
| 392 | m_executionStopTime = DateTime.Now; | ||
| 393 | } | ||
| 394 | } | ||
| 395 | m_processThread = null; | ||
| 396 | } | ||
| 397 | |||
| 398 | #endregion | ||
| 399 | } | ||
| 400 | } | ||