Search code examples
c#winformsraspberry-pimonontp

NTP update causing C# Winforms Timer to pause


I'm running C# mono (linux) on raspberry pi .NET 4.5.

For the purpose of this simple test program, let's say I've got a simple form with a System.Windows.Forms.Timer.

If I let the program run at start-up (before NTP updates the time), the timer runs fine until NTP decides to update the system time. The system time before NTP is a couple of minutes fast; when NTP updates the time, the timer Tick function stops getting called.

After waiting several minutes (about the same time as the clock was fast to begin with) , the timer Tick function continues again as normal.

NTP (network time protocol)

Jul 18 16:02:44 hostname systemd[1]: Started Network Time Synchronization.
Jul 18 16:03:32 hostname systemd-timesyncd[366]: Synchronized to time server for the first time 193.150.34.2:123 (2.debian.pool.ntp.org).

In the above log, the C# program started about the same time as the "Started Network Time Synchronization" and run fine for just under a minute until 16:03:32 when the timer paused.

Designer:

private System.Windows.Forms.Timer LogTimer;

Form1.cs

public void Form1_Load (object sender, EventArgs e)
{
    // Logging interval
    LogTimer.Tick += new System.EventHandler(this.LogTimer_tick);
    LogTimer.Interval = 100;
    LogTimer.Start();
}

private void LogTimer_tick(object sender, EventArgs e)
{
   // do stuff (display time)
   lblTime.Text = DateTime.Now.ToString("dd-MM-yy HH:mm:ss");
}

The question is - how can I detect a system time change (with C# mono on linux) so that I can manually reset the timer Tick continues as normal (such that it doesn't pause) ?


Solution

  • Thanks from the comments - I have tried the following with System.Timers.Timer as suggested and appears to be working so far.

    Form1.cs

    private System.Timers.Timer LogTimer;
    
    public void Form1_Load (object sender, EventArgs e)
    {
        // Logging interval
        LogTimer = new System.Timers.Timer();
        LogTimer.Elapsed += LogTimer_Elapsed;
        LogTimer.SynchronizingObject = this;
        LogTimer.Interval = 100;
        LogTimer.Start();
    }
    
    private void LogTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
       // do stuff (display time)
       lblTime.Text = DateTime.Now.ToString("dd-MM-yy HH:mm:ss");
    }
    

    Also an update to mono is required.