#region Using using System; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; #endregion namespace Wankuma.Interop { /// /// QueryPerformanceCounter を使ったパフォーマンスカウンタです。 /// [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public class InteropQueryPerformanceCounter { #region P/Invoke /// /// P/Invokeネイティブメソッド /// private sealed class NativeMethods { /// /// インスタンス化防止コンストラクタ /// private NativeMethods() { } /// /// 高分解能パフォーマンスカウンタが存在する場合、そのカウンタの現在の値を取得します。 /// /// 1 個の変数へのポインタを指定します。関数から制御が返ると、この変数に、高分解能パフォーマンスカウンタの現在の値が格納されます。インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この変数に 0 が格納されることがあります。 /// インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしている場合、0 以外の値が返ります。関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、GetLastError 関数を使います。たとえば、インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この関数は失敗します。 [DllImport("kernel32.dll")] [SuppressUnmanagedCodeSecurity] public extern static int QueryPerformanceCounter(ref long lpPerformanceCount); /// /// 高分解能パフォーマンスカウンタが存在する場合、そのカウンタの周波数(更新頻度)を取得します。システムが動作している間は、周波数を変更できません。 /// /// 個の変数へのポインタを指定します。関数から制御が返ると、この変数に、高分解能パフォーマンスカウンタの周波数が格納されます。周波数は、1 秒あたりのカウント数として表現されます。インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この変数に 0 が格納されることがあります。 /// ハードウェアが高分解能パフォーマンスカウンタをサポートしている場合は、0 以外の値が返ります。関数が失敗すると、0 が返ります。拡張エラー情報を取得するには、GetLastError 関数を使います。たとえば、インストール先のハードウェアが高分解能パフォーマンスカウンタをサポートしていない場合、この関数は失敗します。 [DllImport("kernel32.dll")] [SuppressUnmanagedCodeSecurity] public extern static int QueryPerformanceFrequency(ref long lpFrequency); } #endregion #region メンバ private long _StratTime = 0; private long _EndTime = 0; private long _Frequency = 0; #endregion #region public long Frequency /// /// 分解能を取得します。 /// /// このシステムではQueryPerformanceCounterが対応していません。 public long Frequency { get { if (this._Frequency != 0 ) { return this._Frequency; } else { if ( NativeMethods.QueryPerformanceFrequency(ref this._Frequency) == 0 ) { throw new NotSupportedException("このシステムでは対応していません。"); } else { return this._Frequency; } } } } #endregion #region public void Start() /// /// 計測を開始します /// /// このシステムではQueryPerformanceCounterが対応していません。 public void Start() { if ( NativeMethods.QueryPerformanceCounter(ref this._StratTime) == 0 ) { throw new NotSupportedException("このシステムでは対応していません。"); } } #endregion #region public void End() /// /// 計測を終了します /// /// このシステムではQueryPerformanceCounterが対応していません。 public void End() { if ( NativeMethods.QueryPerformanceCounter(ref this._EndTime) == 0 ) { throw new NotSupportedException("このシステムでは対応していません。"); } } #endregion #region public double Result /// /// Start()で計測を開始し、End()までの計測結果を返します。 /// /// このシステムではQueryPerformanceCounterが対応していません。 public double Result { get { return (this._EndTime - this._StratTime) * 1.0f / (double)this.Frequency; } } #endregion #region public double NowResult /// /// Start()で計測を開始し、現在時点での計測結果を返します /// /// このシステムではQueryPerformanceCounterが対応していません。 public double NowResult { get { long NowTime = 0; if ( NativeMethods.QueryPerformanceCounter(ref NowTime) == 0 ) { throw new NotSupportedException("このシステムでは対応していません。"); } return (NowTime - this._StratTime) * 1.0f / (double)this.Frequency; } } #endregion } }