how to set timer resolution from C# to 1 ms?

前端 未结 2 1483
天涯浪人
天涯浪人 2020-11-29 11:30

I\'ve used this tool and noticed that my Windows Server 2008 R2 Standard has a 15 ms resolution while Windows 8 has a 1 ms resolution timer.

I would prefer to set th

相关标签:
2条回答
  • 2020-11-29 11:53

    Better code to implement this would be:

    using System;
    using System.Runtime.InteropServices;
    using System.Threading;
    
    internal sealed class TimePeriod : IDisposable
    {
        private const string WINMM = "winmm.dll";
    
        private static TIMECAPS timeCapabilities;
    
        private static int inTimePeriod;
    
        private readonly int period;
    
        private int disposed;
    
        [DllImport(WINMM, ExactSpelling = true)]
        private static extern int timeGetDevCaps(ref TIMECAPS ptc, int cbtc);
    
        [DllImport(WINMM, ExactSpelling = true)]
        private static extern int timeBeginPeriod(int uPeriod);
    
        [DllImport(WINMM, ExactSpelling = true)]
        private static extern int timeEndPeriod(int uPeriod);
    
        static TimePeriod()
        {
            int result = timeGetDevCaps(ref timeCapabilities, Marshal.SizeOf(typeof(TIMECAPS)));
            if (result != 0)
            {
                throw new InvalidOperationException("The request to get time capabilities was not completed because an unexpected error with code " + result + " occured.");
            }
        }
    
        internal TimePeriod(int period)
        {
            if (Interlocked.Increment(ref inTimePeriod) != 1)
            {
                Interlocked.Decrement(ref inTimePeriod);
                throw new NotSupportedException("The process is already within a time period. Nested time periods are not supported.");
            }
    
            if (period < timeCapabilities.wPeriodMin || period > timeCapabilities.wPeriodMax)
            {
                throw new ArgumentOutOfRangeException("period", "The request to begin a time period was not completed because the resolution specified is out of range.");
            }
    
            int result = timeBeginPeriod(period);
            if (result != 0)
            {
                throw new InvalidOperationException("The request to begin a time period was not completed because an unexpected error with code " + result + " occured.");
            }
    
            this.period = period;
        }
    
        internal static int MinimumPeriod
        {
            get
            {
                return timeCapabilities.wPeriodMin;
            }
        }
    
        internal static int MaximumPeriod
        {
            get
            {
                return timeCapabilities.wPeriodMax;
            }
        }
    
        internal int Period
        {
            get
            {
                if (this.disposed > 0)
                {
                    throw new ObjectDisposedException("The time period instance has been disposed.");
                }
    
                return this.period;
            }
        }
    
        public void Dispose()
        {
            if (Interlocked.Increment(ref this.disposed) == 1)
            {
                timeEndPeriod(this.period);
                Interlocked.Decrement(ref inTimePeriod);
            }
            else
            {
                Interlocked.Decrement(ref this.disposed);
            }
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct TIMECAPS
        {
            internal int wPeriodMin;
    
            internal int wPeriodMax;
        }
    }
    

    Use it via:

    using (new TimePeriod(1))
    {
        ////...
    }
    
    0 讨论(0)
  • 2020-11-29 12:03

    You can try this:

    public static class WinApi
    {
        /// <summary>TimeBeginPeriod(). See the Windows API documentation for details.</summary>
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage"), SuppressUnmanagedCodeSecurity]
        [DllImport("winmm.dll", EntryPoint="timeBeginPeriod", SetLastError=true)]
    
        public static extern uint TimeBeginPeriod(uint uMilliseconds);
    
        /// <summary>TimeEndPeriod(). See the Windows API documentation for details.</summary>
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Interoperability", "CA1401:PInvokesShouldNotBeVisible"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage"), SuppressUnmanagedCodeSecurity]
        [DllImport("winmm.dll", EntryPoint="timeEndPeriod", SetLastError=true)]
    
        public static extern uint TimeEndPeriod(uint uMilliseconds);
    }
    

    And use it like this:

    WinApi.TimeBeginPeriod(1);
    

    And to go back to how it was:

    WinApi.TimeEndPeriod(1);
    
    0 讨论(0)
提交回复
热议问题