我想做一个行为如下的计时器:
如果任务/作业的处理时间小于计时器间隔,则在(timer.interval - 处理时间作业/作业)中启动计时器
如果作业/任务的处理时间超过计时器间隔,则立即开始下一个作业/任务
下面的代码有效,但我想知道为什么在 ElapsedEventHandler 方法中作业/任务必须首先完成,然后我们可以设置新的计时器间隔。System.Timers.Timer 的 Elapsed 事件在间隔已过时引发。使用 AutoReset = false 选项,我们设置 Timer 在第一个 Interval 过去后只引发一次 Elapsed 事件。然后我们必须手动调用 Timer.Start() 来重新启动它。
using System;
using System.Timers;
namespace TestTimer
{
class Program
{
private static Timer t;
private static double intervalMiliseconds;
static void Main(string[] args)
{
intervalMiliseconds = 5000; // 5 seconds
t = new Timer();
t.Interval = intervalMiliseconds;
t.AutoReset = false;
t.Elapsed += new ElapsedEventHandler(OnTimedEvent);
t.Start();
log("Timer started at " + DateTime.Now.ToString());
log("Interval is: " + defaultIntervalMiliseconds);
Console.ReadKey();
}
private static void log(string text)
{
Console.WriteLine(text + "\n");
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
// if t.Interval is set here thread just kills the job if it
// runs longer than interval
t.Interval = intervalMiliseconds;
log("ElapsedEvent triggered at " + DateTime.Now.ToString());
// job
DateTime startTime = DateTime.Now;
log("job started" );
System.Threading.Thread.Sleep(8000); // 8 sec
log("job ended" );
TimeSpan jobTime = DateTime.Now.Subtract(startTime);
log("job took " + jobTime.TotalSeconds + " seconds");
// if we set t.Interval here it works so first the job
// must be done and than we can set timer interval ? why ?
//t.Interval = intervalMiliseconds;
if (jobTime.TotalMilliseconds < t.Interval)
{
t.Interval = t.Interval - jobTime.TotalMilliseconds;
log("Job ended Earlier starting Event in: " + t.Interval);
}
else
{
t.Interval = 100;
log("Job overpass interval. Current time: " +
DateTime.Now.ToString());
}
t.AutoReset = false;
t.Start();
}
}
}
结果:
如果我们在方法 OnTimedEvent 的开头注释 t.Interval 并在工作完成后取消注释 t.Interval 一切正常。结果:
为什么我们不能在方法 OnTimedEvent 开始时设置计时器间隔。如果我们在任务/作业运行时间超过计时器间隔的情况下这样做,线程只会终止该作业。如果有人有一些想法,我将不胜感激?这是否与线程与主线程(哪个计时器运行)的同步有关?当我们调用方法 OnTimedEvent 时,计时器将不会再次调用该方法,因为它具有 AutoReset = false,那么在设置计时器属性的地方有什么区别?