Accurate three-minute time timer intervals

2019-09-20 15:56发布

问题:

In my previos question I asked about rounding time value to nearest third-minute. Well now I have some issues with my System.Threading.Timer that must work when is third-minute time is come. I Do following:

private System.Timers.Timer WorkTimer;
//...
public void StartProccessing()
{
WorkTimer = new System.Timers.Timer();
WorkTimer.AutoReset = false;
WorkTimer.Elapsed += new ElapsedEventHandler(WorkTimer_Elapsed);
StartWorkTimer();
}
//...
private void StartWorkTimer()
        {
            WorkTimer.Interval = (CurrentTime.AddMinutes(3) - DateTime.Now).TotalMilliseconds;
            WorkTimer.Start();
        }
void WorkTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            WorkTimer.Stop();
            this.ProcessData(this.CurrentTime);
            StartWorkTimer();
        }

Problem is that the when timer started - it is not work in first third-minute time, its begin working after second third-minute time. For example: Timer is started at 15.02.2012 12:20:32.871, in 15.02.2012 12:21:00.000 it must work WorkTimer_Elapsed, but its begin from 15.02.2012 12:24:01.871. How to fix this? I fix my CurrentTime time (from previos question):

private DateTime CurrentTime
        {
            get
            {
                DateTime now = DateTime.Now.AddSeconds(30);
                DateTime val;
                val = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0)
                     .AddMinutes(((now.Minute) / 3) * 3 - now.Minute);
                return val;
            }
        }

回答1:

The problem here is that you round to the nearest 3rd minute, but for your timer to work you have to use the most recent one.

So, if you remove the AddSeconds(30), your timer should work as expected.

On a side note: your rounding algorithm should add 90 seconds (as that's the half of 3 minutes) rather than 30. If you're adding 30 seconds to 12:31:50, you'd end up with 12:30:00, but it should be 12:33:00 instead.



回答2:

Use the System.Threading.Timer class.

DateTime dt = ... // here you assign the start time, so you can calculate
                  // the first time you want to start it.
var timer = new Timer(callback, null, dt, TimeSpan.FromMinutes(3));

Callback is:

public delegate void TimerCallback(Object state)