/// <summary> /// Function to retrieve the timeGetTime time data. /// </summary> private void GetWin32Time() { if (!_initialized) { Reset(); } long currentTime = WinMultimediaApi.timeGetTime(); long ticks = Environment.TickCount; // Handle wrap around every ~50 days. if (currentTime < _startTime) { long diff = uint.MaxValue - _startTime; _startTime = diff; currentTime += diff; } if (ticks < _startTick) { long diff = uint.MaxValue - _startTick; _startTick = diff; ticks += diff; } unchecked { _milliseconds = (currentTime - _startTime); _currentTicks = ticks - _startTick; } }
/// <summary> /// Function to end the timing period for the timer. /// </summary> /// <remarks> /// <para> /// This will end the current timing period for calls to the Win32 <a href="https://msdn.microsoft.com/en-us/library/dd757629(v=vs.85).aspx" target="_blank">timeGetTime</a> API function. /// </para> /// <para> /// Calls to this method must be paired with the <see cref="BeginTiming"/> static method, otherwise the system will be left in a state where the task scheduler switches tasks more often and the power /// saving may not trigger properly. If <see cref="BeginTiming"/> was never called, then this method will do nothing. /// </para> /// </remarks> /// <exception cref="Win32Exception">Thrown when the last known period value is out of range.</exception> public static void EndTiming() { if (_lastPeriod == null) { return; } if (WinMultimediaApi.timeEndPeriod((uint)_lastPeriod.Value) == ErrorNoCanDo) { throw new Win32Exception(Resources.GOR_ERR_TIME_CANNOT_END); } _lastPeriod = null; }
/// <summary> /// Function to reset the timer. /// </summary> /// <exception cref="Win32Exception">Thrown when timer information cannot be retrieved from the operating system.</exception> public void Reset() { if (WinMultimediaApi.timeGetDevCaps(ref _timeCaps, Unsafe.SizeOf <TIMECAPS>()) != 0) { throw new Win32Exception(Resources.GOR_ERR_TIME_CANNOT_BEGIN); } if (_lastPeriod != null) { int period = _lastPeriod.Value; EndTiming(); BeginTiming(period); } _startTick = Environment.TickCount; _startTime = WinMultimediaApi.timeGetTime(); _initialized = true; }
/// <summary> /// Function to set the timing period for the timer. /// </summary> /// <param name="period">[Optional] Minimum timer resolution, in milliseconds, for the application or device driver. A lower value specifies a higher (more accurate) resolution..</param> /// <remarks> /// <para> /// This will set the timing period for calls to the Win32 <a href="https://msdn.microsoft.com/en-us/library/dd757629(v=vs.85).aspx" target="_blank">timeGetTime</a> API function so that the resolution for the timer /// can be adjusted for maximum performance. /// </para> /// <para> /// Calls to this method must be paired with the <see cref="EndTiming"/> static method, otherwise the system will be left in a state where the task scheduler switches tasks more often and the power /// saving may not trigger properly. /// </para> /// </remarks> /// <exception cref="Win32Exception">Thrown when the <paramref name="period"/> value is out of range.</exception> public static void BeginTiming(int period = 1) { if (_lastPeriod != null) { EndTiming(); } if (period < _timeCaps.MinPeriod) { period = (int)_timeCaps.MinPeriod; } if (WinMultimediaApi.timeBeginPeriod((uint)period) == ErrorNoCanDo) { throw new Win32Exception(Resources.GOR_ERR_TIME_CANNOT_BEGIN); } _lastPeriod = period; }