2015-05-02 155 views
0

我在定時器中遇到了一個奇怪的問題。只要我知道,定時器的interval屬性表示timer_Tick事件將被觸發的循環之間的延遲。延遲15毫秒的計時器觸發嘀嗒事件

在使用Visual Basic進行編程之前,我遇到了確切簽名(15和16毫秒延遲)的問題。我創建的任何定時器都會以15或16毫秒的延遲觸發它們的滴答事件。例如,如果我將計時器的時間間隔設置爲1(這意味着其tick事件應該在1秒內被觸發1000次),則該事件會在1秒內被觸發62至66次(即1000/16至1000/15 )。

自從5年前我一直在開發VB應用程序,並且始終存在此問題(這也意味着我在具有AMD和Intel處理器的幾個不同系統上出現此問題),現在我再次使用C# 。

我設法做了一個解決方法,並通過計算每次基於TickCount方法(VB中的GetTickCount API和C#中的Environment.TickCount)觸發滴答事件之間的時差來解決此問題。

* TickCount是自系統啓動以來經過的毫秒數。

爲了更好地理解問題,我創建了一個Windows應用程序,它可以計算從執行它以來的秒數(如計時器)。每次Tick事件被觸發時,它都依賴於TickCount和普通的添加。它還通過從TickCount的當前值中減去TickCount的最後一個值來計算定時器的延遲(如果定時器真的在1秒內被激發1000次,則TickCount的差值每次爲1,因此這意味着沒有延遲,但是如果差異超過1,那麼計時器的tick事件被觸發時每次都會有一些延遲)。

下面的代碼:

public partial class Form1 : Form 
{ 
    int localTime = 0, systemTime = 0, baseSystemTime = 0, lastSystemTime = 0; 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     // Calculate time based on TickCount 
     if (baseSystemTime == 0) 
      baseSystemTime = Environment.TickCount; 

     systemTime = Environment.TickCount - baseSystemTime; 
     label2.Text ="System Time: " + ((systemTime/1000)/60).ToString() + ":" + ((systemTime/1000) % 60).ToString(); 

     // Calculate time based on timer1_Tick 
     localTime++; 
     label1.Text = "Application Time: " + ((localTime/1000)/60).ToString() + ":" + ((localTime/1000) % 60).ToString(); 

     // Calculate the delay 
     if (lastSystemTime > 0) 
     { 
      label3.Text = "Delay: " + (Environment.TickCount - lastSystemTime).ToString() + " ms"; 
     } 

     lastSystemTime = Environment.TickCount; 
    } 
} 

我還上傳這裏整個解決方案:http://ramt.in/test/TimerDelay.zip

下面是由應用而17秒計數的應用程序(具有15毫秒延遲和1秒的屏幕截圖實際上已經過去了!):

Screen Shot

解決辦法只有50KB,所以請隨意下載並運行它,看看你是否得到和我一樣的結果。如果它是一樣的,那麼微軟世界裏的定時器課程就會出現問題!

但更重要的是,如果有人知道什麼可能會導致此延遲,請與我分享您的知識。

+0

的可能重複的[計時器不與時間跨度從毫秒工作良好(http://stackoverflow.com/questions/26703794/timer-is-not-working-well-with-timespan-from-milliseconds) –

+0

視窗不是實時的,所以這會發生。看看這個http://ideveloper-dotnet.blogspot.com/2013/07/real-time-timer-in-c.html –

回答

1

這是一個不是c#或VB的系統問題。要檢查的是如何準確系統的玩具可以用Stopwatch類和兩個屬性

  1. IsHighResolution - The timer used by the Stopwatch class depends on the system hardware and operating system. IsHighResolution is true if the Stopwatch timer is based on a high-resolution performance counter. Otherwise, IsHighResolution is false, which indicates that the Stopwatch timer is based on the system timer.
  2. 頻率

MSDN以下代碼顯示了它是如何工作

public static void DisplayTimerProperties() 
{ 
    // Display the timer frequency and resolution. 
    if (Stopwatch.IsHighResolution) 
    { 
     Console.WriteLine("Operations timed using the system's high-resolution performance counter."); 
    } 
    else 
    { 
     Console.WriteLine("Operations timed using the DateTime class."); 
    } 

    long frequency = Stopwatch.Frequency; 
    Console.WriteLine(" Timer frequency in ticks per second = {0}", 
     frequency); 
    long nanosecPerTick = (1000L*1000L*1000L)/frequency; 
    Console.WriteLine(" Timer is accurate within {0} nanoseconds", 
     nanosecPerTick); 
} 

UPDATE

您還在你的代碼做了一個錯誤:

 // Calculate time based on timer1_Tick 
     localTime++; 
     label1.Text = "Application Time: " + ((localTime/1000)/60).ToString() + ":" + ((localTime/1000) % 60).ToString(); 

這行沒有什麼時間該過去了。它僅計算運行次數timer1_Tick。 1毫秒的間隔對Windows窗體計時器來說太小了。你可以閱讀這個在這裏:Timer takes 10 ms more than interval

如果您需要更精確的計時器,你可以看一下這篇文章Microsecond and Millisecond C# Timer

+0

做了它並得到了這些結果:IsHighResolution返回true,頻率爲2338336,精度是427納秒。這是什麼意思? –

+0

@RamtinSoltani我更新了我的答案 –

+0

我看了文章(Microsecond Timer),這是我正在尋找的,但只有一個問題,那就是跨線程問題。我該如何解決它?是否有一個等同於SynchronizingObject的屬性? –

2

這有什麼好做實時或不:Windows默認的計時器分辨率是64刻度/秒15.625毫秒。然而,可以修改系統定時器分辨率以在更高分辨率下工作,例如, 1毫秒。請參閱this查看問題「」爲什麼.NET定時器限制爲15毫秒分辨率?「瞭解如何修改系統定時器分辨率。

+0

有沒有比改變定時器分辨率更好的方法?將使用System.Timers.Timer而不是System.Windows.Forms.Timer(VS工具箱中的默認計時器)會帶來更高的準確性嗎? –

+0

不幸的不是。但是,你可以看看[如何將計時器分辨率從C#設置爲1 ms?](http://stackoverflow.com/q/15071359/1504523)以查看c#示例。但是你也應該記住[爲什麼通過timeBeginPeriod提高定時器分辨率會影響功耗?](http://stackoverflow.com/q/7590475/1504523)。 – Arno