2013-04-23 86 views
3

如下片段爲什麼是最小Threading.Timer間隔爲15ms,儘管timeBeginPeriod(1)

[DllImport("winmm.dll", EntryPoint = "timeBeginPeriod")] 
    public static extern uint TimeBeginPeriod(uint uMilliseconds); 

    static void Main(string[] args) 
    { 
     if (TimeBeginPeriod(1) != 0) 
      Console.WriteLine("TimeBeginPeriod failed!"); 

     Console.WriteLine("Sleep"); 
     Stopwatch sw = Stopwatch.StartNew(); 
     for (int i = 0; i < 10; i++) 
     { 
      Thread.Sleep(1); 
      Console.WriteLine(sw.ElapsedTicks * 1000d/Stopwatch.Frequency); 
      sw.Restart(); 
     } 

     Console.WriteLine("Threading.Timer"); 
     sw = null; 
     System.Threading.Timer t = null; 
     int n = 0; 

     t = new Timer(state => 
     { 
      if (sw == null) 
       sw = Stopwatch.StartNew(); 
      else 
      { 
       Console.WriteLine(sw.ElapsedTicks * 1000d/Stopwatch.Frequency); 
       n++; 
       sw.Restart(); 
      } 
      if (n == 10) 
       t.Change(Timeout.Infinite, Timeout.Infinite); 
     }, null, TimeSpan.FromMilliseconds(1), TimeSpan.FromMilliseconds(1)); 
     Console.ReadKey(); 
    } 

將例如產生此輸出:

Sleep 
0.151834939915548 
0.757358826331279 
0.786901687225611 
0.712520725399457 
0.715593741662697 
0.798704863327602 
0.5724889615859 
0.648825479215934 
0.436927039609783 
0.517873081634677 
Threading.Timer 
15.5841035662354 
14.8620145856526 
15.1098812837944 
14.4202684978119 
15.3883384620112 
14.7210748852159 
15.307462261265 
15.7125416777831 
14.5991320125882 
15.6035194417168 

根據網絡comment by Hans Passant,timeBeginPeriod會影響常規(.net)定時器。那麼爲什麼我的計時器仍然有這個粗粒度? Thread.Sleep似乎做得很好。

也許相關:它運行在Windows 7,64bit,.net 4,VMWare內部。

回答

5

該評論是錯誤的。我的經驗是多媒體計時器不會影響.NET定時器。也就是說,它不會更改其最短支持時間段,似乎大約爲15毫秒。它可能提高其準確性。也就是說,如果你問16毫秒,你實際上可能會得到16毫秒,而不是「15到30毫秒之間」。

爲什麼.NET定時器限制爲15毫秒對我來說不是很清楚。

在接受的答案here中有一些相關信息。

如果您正在爲.NET尋找更高分辨率的計時器,那麼您可能不應使用多媒體計時器。這些在Windows API中已被棄用。使用計時器隊列計時器。請參閱我的文章:

另一種選擇是使用Waitable Timer。完整的源代碼可在http://www.mischel.com/pubs/waitabletimer.zip

相關問題