2013-02-25 23 views
7

Tôi đã sử dụng this tool và nhận thấy rằng Windows Server 2008 R2 Standard của tôi có độ phân giải 15 ms trong khi Windows 8 có bộ hẹn giờ có độ phân giải 1 mili giây.cách đặt độ phân giải hẹn giờ từ C# thành 1 ms?

Tôi muốn đặt Độ phân giải bộ hẹn giờ thành 1 ms trên Windows Server 2008 R2 vì tôi đang chạy phần mềm có độ trễ thấp trên đó.

Tôi đã tìm thấy điều này msdn article, nhưng nó không giải thích cách thay đổi độ phân giải hẹn giờ từ chương trình C#. Làm thế nào để làm điều đó?

+0

Tôi tin rằng giờ giải quyết được hạn chế về kiến ​​trúc nhất định (ví dụ: bạn không thể chỉ đặt nó thấp hơn). [Ở đây] (http://msdn.microsoft.com/en-us/magazine/cc163996.aspx) là một bài viết về cách triển khai bộ đếm thời gian có độ phân giải cao của riêng bạn cho Windows (với ví dụ về mã). – NominSim

+0

@NominSim bạn đã đọc bài viết "Thu thập và đặt Độ phân giải hẹn giờ" được đề cập trong câu hỏi chưa? – javapowered

+0

Có. Nếu bạn đọc bài viết tôi đã liên kết đến, nó giải thích cách độ phân giải bị giới hạn theo kiến ​​trúc. Bạn có thể nhận được độ phân giải tốt hơn, nhưng có những thỏa hiệp mà bạn phải thực hiện là tốt. (Bạn không thể chỉ thiết lập độ phân giải tùy ý mà không bị mất một số độ chính xác). – NominSim

Trả lời

11

Bạn có thể thử này:

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

Và sử dụng nó như thế này:

WinApi.TimeBeginPeriod(1); 

Và để trở lại như thế nào đó là:

WinApi.TimeEndPeriod(1); 
+1

Tôi có nên gọi chức năng này mỗi lần khởi động lại hệ thống không? hoặc tôi nên gọi nó một lần? – javapowered

+2

Bất cứ khi nào bạn khởi động hệ thống. Nó không tồn tại - nhưng nó * là * toàn cầu (tức là nó sẽ ảnh hưởng đến tất cả các quá trình)! –

+0

Tôi đã sử dụng phương pháp này - nó ảnh hưởng đến Sleeps và OS timer, tuy nhiên Threading.Timer giữ độ phân giải 15ms - chi tiết hơn trong câu hỏi của tôi ở đây: http://stackoverflow.com/questions/23215970/system-threading-timer- vs-system-threading-thread-sleep-resolution-net-timer – Jan

5

Better mã để thực hiện điều này sẽ là:

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

Sử dụng nó thông qua:

using (new TimePeriod(1)) 
{ 
    ////... 
} 
Các vấn đề liên quan