Source/Tx.Windows/PerfCounters/PerfCounterRealTimeProbe.cs (70 lines of code) (raw):

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System; using System.Threading; namespace Tx.Windows { public sealed class PerfCounterRealTimeProbe : PerfCounterReader { private bool _firstMove = true; private Timer _timer; private bool _disposed = false; public PerfCounterRealTimeProbe(IObserver<PerformanceSample> observer, TimeSpan samplingRate, params string[] counterPaths) : base(observer) { if (counterPaths == null) { throw new ArgumentNullException(nameof(counterPaths)); } PdhStatus status = PdhNativeMethods.PdhOpenQuery(null, IntPtr.Zero, out _query); PdhUtils.CheckStatus(status, PdhStatus.PDH_CSTATUS_VALID_DATA); for (int i=0; i<counterPaths.Length; i++) { AddCounter(counterPaths[i], i); } _timer = new Timer(OnTimer, null, TimeSpan.Zero, samplingRate); } public void OnTimer(object state) { try { if (_firstMove) { // some counters need two samples to calculate their value // so skip a sample to make sure there are no further complications PdhNativeMethods.PdhCollectQueryData(_query); _firstMove = false; return; } long time; PdhStatus status = PdhNativeMethods.PdhCollectQueryDataWithTime(_query, out time); PdhUtils.CheckStatus(status, PdhStatus.PDH_CSTATUS_VALID_DATA); DateTime timestamp = TimeUtil.FromFileTime(time); foreach (PerfCounterInfo counterInfo in _counters) { ProduceCounterSamples(counterInfo, timestamp); } } catch (Exception ex) { _observer.OnError(ex); } } protected override void Dispose(bool disposing) { if (this._disposed) return; if (disposing) { if (_timer != null) { _timer.Dispose(); _timer = null; } } this._disposed = true; // Call base class implementation. base.Dispose(disposing); } ~PerfCounterRealTimeProbe() { Dispose(); } } }