//****************************************************************************************************** // ProcessUtilizationCalculator.cs - Gbtc // // Copyright © 2018, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this // file except in compliance with the License. You may obtain a copy of the License at: // // http://opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 02/05/2018 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using System; using System.Diagnostics; using System.Timers; namespace GSF.Diagnostics { /// /// Represents a utilization calculator for a . /// public sealed class ProcessUtilizationCalculator : IDisposable { #region [ Members ] // Constants /// /// Default value for the property. /// public const int DefaultUpdateInterval = 5000; // Fields private readonly Timer m_updateUtilizationTimer; private WeakReference m_processReference; private int m_updateInterval; private TimeSpan m_startTime; private TimeSpan m_lastProcessorTime; private DateTime m_lastMonitorTime; private bool m_disposed; #endregion #region [ Constructors ] /// /// Creates a new . /// public ProcessUtilizationCalculator() { m_updateInterval = DefaultUpdateInterval; m_lastProcessorTime = new TimeSpan(0L); m_updateUtilizationTimer = new Timer(m_updateInterval) { AutoReset = true, Enabled = false }; m_updateUtilizationTimer.Elapsed += UpdateUtilizationTimerElapsed; } #endregion #region [ Properties ] /// /// Gets the current processor utilization of the associated . /// public double Utilization { get; private set; } /// /// Gets or sets the interval, in milliseconds, over which will be calculated. /// public int UpdateInterval { get { return m_updateInterval; } set { m_updateInterval = value; if (m_updateInterval > 0) m_updateUtilizationTimer.Interval = m_updateInterval; } } /// /// Gets associated process for this . /// /// /// The maintains a to the associated /// so this property can be null if the process is no longer available. /// public Process AssociatedProcess { get { Process process = null; m_processReference?.TryGetTarget(out process); return process; } } #endregion #region [ Methods ] /// /// Releases all the resources used by the object. /// public void Dispose() { if (m_disposed) return; try { m_updateUtilizationTimer.Stop(); m_updateUtilizationTimer.Elapsed -= UpdateUtilizationTimerElapsed; m_updateUtilizationTimer.Dispose(); } finally { m_disposed = true; // Prevent duplicate dispose. } } /// /// Starts calculating the processor utilization of the specified . /// /// The to monitor for processor utilization. public void Initialize(Process process) { m_processReference = new WeakReference(process); m_startTime = process.TotalProcessorTime; m_lastMonitorTime = DateTime.UtcNow; if (m_updateInterval > 0) m_updateUtilizationTimer.Start(); } private void UpdateUtilizationTimerElapsed(object sender, ElapsedEventArgs e) { try { Process process; if ((object)m_processReference != null && m_processReference.TryGetTarget(out process) && !process.HasExited) { DateTime currentTime = DateTime.UtcNow; TimeSpan processorTime = process.TotalProcessorTime - m_startTime; Utilization = (processorTime - m_lastProcessorTime).TotalSeconds / (Environment.ProcessorCount * currentTime.Subtract(m_lastMonitorTime).TotalSeconds); m_lastMonitorTime = currentTime; m_lastProcessorTime = processorTime; } else { Utilization = 0.0D; m_updateUtilizationTimer.Enabled = false; } } catch { Utilization = 0.0D; m_updateUtilizationTimer.Enabled = false; } } #endregion } }