Tuesday, January 30, 2024

[SOLVED] NTP update causing C# Winforms Timer to pause

Issue

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.



Answered By - pm101
Answer Checked By - Mary Flores (WPSolving Volunteer)