以特定间隔执行活动

时间:2016-09-16 19:30:17

标签: c# .net

我的C#应用​​程序必须每隔几秒执行一次任务。执行恰好在这个间隔发生是非常重要的;给予或花费几毫秒。

我尝试使用定时器,但几分钟后时间逐渐变化。 我使用的代码如下:

System.Timers.Timer timerObj = new System.Timers.Timer(10 * 1000);
timerObj.Elapsed += timerObj_Elapsed;
timerObj.AutoReset = true;
timerObj.Start();

static void timerObj_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
  DateTime currentTime = DateTime.Now;
  Console.WriteLine(currentTime.ToString("HH:mm:ss.fff"));
}

enter image description here

有没有更好的方法来进行这种活动?

3 个答案:

答案 0 :(得分:3)

如果确切地说这非常重要,请将计时器的间隔设置为小于您可以关闭的最大毫秒数。 (希望这将大于15ms,因为它是System.Timers.Timer的分辨率。)然后,在tick处理程序中,检查是否已经过了适当的时间量,如果是,则调用&# 34;实&#34;处理程序。如果您的目标是避免漂移,那么您对是否开火时间的测试应该基于自启动计时器以来经过的时间,而不是自上次开始计时以来所经过的时间。&#34; < / p>

答案 1 :(得分:1)

您可以尝试始终通过AutoReset = false安排一个singelshot计时器,并计算计时器应该触发的delta。这应该补偿你的偏差,因为它从绝对时间计算增量。这是一个粗略的例子:

// member variables
DateTime firstSchedule = DateTime.UtcNow;
var numElapsed = 1;

constructor()
{
    this.timerObj = new System.Timers.Timer();
    timerObj.Interval = CalcDelta();
    timerObj.Elapsed += timerObj_Elapsed;
    timerObj.AutoReset = false;
    timerObj.Start();
}

void timerObj_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    this.numElapses++;
    this.timerObj.Interval = CalcDelta();
    this.timerObj.Start();

    DateTime currentTime = DateTime.Now;
    Console.WriteLine(currentTime.ToString("HH:mm:ss.fff"));
}


private long CalcDelta()
{
    DateTime nextSchedule = firstSchedule + TimeSpan.FromSeconds(numElapses * 10);
    return (nextSchedule - DateTime.UtcNow).TotalMilliseconds;  
}

答案 2 :(得分:0)

    private void setTimerRepeat(object sender, DoWorkEventArgs e){
        DateTime begin = DateTime.Now;
        bool isRunning = true;
        int sleep=500;
        while(isRunning){
            int milliSeconds = DateTime.Now.Subtract(begin).TotalMilliSeconds;
            if(milliSeconds > 9000){
                sleep=10;
            }else{
                sleep=500;
            }
            if(milliSeconds=>10000){//if you get drift here, it should be consistent - adjust firing time downward to offset drift (change sleep to a multiple such that sleep%yourNumber==0)
                begin = DateTime.Now;
                Task.Run(()=>fireEvent());
            }
            Thread.Sleep(sleep);

        }
   }
}