如何每分钟调用一个方法,但考虑到该方法处理所需的时间可能需要不止一个?

时间:2017-08-03 19:57:34

标签: c# windows-services

我正在开发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);
    }
}

那么,我怎么能每分钟调用我的方法但是当方法超过一分钟时它将等待N分钟(假设30秒),然后通过调用方法重新开始。

2 个答案:

答案 0 :(得分:1)

这样的事情应该有效。将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)

答案 1 :(得分:0)

根据您的需要,有两种解决方案。你想每分钟做一次工作,总是等下一分钟吗?或者你想每分钟运行不超过一次但如果你落后就可以“赶上”?

换句话说,如果处理需要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();
}