如何将定时器分辨率从c#设置为1毫秒

本文关键字:设置 1毫秒 分辨率 定时器 | 更新日期: 2023-09-27 18:01:15

我已经使用了这个工具,并注意到我的Windows Server 2008 R2标准有一个15毫秒的分辨率,而Windows 8有一个1毫秒的分辨率定时器。

我更喜欢在Windows Server 2008 R2上设置定时器分辨率为1毫秒,因为我在它上运行低延迟软件。

我找到了这篇msdn文章,但它没有解释如何从c#程序更改计时器分辨率。我怎么做呢?

如何将定时器分辨率从c#设置为1毫秒

你可以试试:

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);
}

并像这样使用:

WinApi.TimeBeginPeriod(1);

回到原来的样子:

WinApi.TimeEndPeriod(1);

更好的代码是:

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;
    }
}

使用方式:

using (new TimePeriod(1))
{
    ////...
}