如何每分钟调用一次方法,但要考虑该方法处理所花费的时间可能需要多次?
我正在开发windows服务,我想每分钟致电OnStart
。我原本有一个永远的while循环,但然后服务不会安装。如何每分钟调用一次方法,但要考虑该方法处理所花费的时间可能需要多次?
while (true)
{
Stopwatch stopWatch = new Stopwatch();
int totalTime = 0;
stopWatch.Start();
MethodToCall();
stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;
totalTime = ts.Seconds * 1000 + ts.Milliseconds;
if (totalTime < 60000)
{
Thread.Sleep(60000 - totalTime);
//ManualResetEvent.WaitOne(10000);
}
else
{
Thread.Sleep(30000);
}
}
所以,我怎样才能让我的方法每分钟的电话,但是当该方法已经超过1分钟,它将等待分钟数为n(比方说30秒),然后通过调用该方法重新开始。
像这样的东西应该工作。在AutoReset
标志设置为false的情况下,定时器将仅在指定的interval
时间之后触发一次。在finally
区块中,我们确保重新启动定时器倒计时,等待间隔时间再次结束。
var interval = TimeSpan.FromMinutes(1);
var timer = new System.Timers.Timer(interval.TotalMilliseconds) { AutoReset = false };
timer.Elapsed += (sender, eventArgs) =>
{
var start = DateTime.Now;
try
{
// do work
}
finally
{
var elapsed = DateTime.Now - start;
if (elapsed < interval)
timer.Interval = (interval - elapsed).TotalMilliseconds;
else
timer.Interval = TimeSpan.FromSeconds(30).TotalMilliseconds;
timer.Start();
}
};
timer.Start();
Source for Timer.Elapsed
(note the bit about setting Interval
resetting the countdown)
随着'AutoReset = false',计时器赢得了不会重置,只会触发一次,除非再次调用Start()。尽管它不需要try/finally块,但我想 –
定时器事件将在每隔'间隔'秒数上升,这可以防止同时引发多次'Elapsed'事件:[Timer.Event ](https://msdn.microsoft.com/en-us/library/system.timers.timer.elapsed(v = vs.110).aspx) –
为了让我的问题更清楚,如果让我们坐下来,方法需要59秒,然后休息一秒钟,然后重新开始。如果需要159秒,它可以运行,只要花费30秒就可以运行(或者我可以让它立即开始) – jjss
有这取决于你想要什么两种解决方案。你想每分钟做一次工作,并总是等待下一分钟吗?或者你想每分钟运行一次,但是如果你落后了,可以“赶上”吗?
换句话说,如果处理需要80秒,那么下一个工作是立即开始还是等到T = 120?
首先是容易的,但请注意,我没有测试过这一点,它只是一个指导方针:
AutoResetEvent waitHandle = new AutoResetEvent(false);
System.Timer(() => waitHandle.Set(), null, TimeSpan.FromMinutes(1), TimeSpan.FromMilliseconds(-1));
while (true)
{
// Do stuff
waitHandle.WaitOne();
}
第二只是有点困难。
ManualResetEvent waitHandle = new ManualResetEvent (false);
System.Timer(() => waitHandle.Set(), null, TimeSpan.FromMinutes(1), TimeSpan.FromMilliseconds(-1));
while (true)
{
// Do stuff
waitHandle.Reset();
waitHandle.WaitOne();
}
你想要独立的线程吗? – Demodave
是否阻塞线程? – bastijn
那么你是说如果运行需要59秒,你希望它在下一秒重新启动,但是如果需要60秒运行,它应该等待30秒后才能重新启动? –