2017-08-03 35 views
0

我正在开发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秒),然后通过调用该方法重新开始。

+0

你想要独立的线程吗? – Demodave

+0

是否阻塞线程? – bastijn

+0

那么你是说如果运行需要59秒,你希望它在下一秒重新启动,但是如果需要60秒运行,它应该等待30秒后才能重新启动? –

回答

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)

+0

随着'AutoReset = false',计时器赢得了不会重置,只会触发一次,除非再次调用Start()。尽管它不需要try/finally块,但我想 –

+0

定时器事件将在每隔'间隔'秒数上升,这可以防止同时引发多次'Elapsed'事件:[Timer.Event ](https://msdn.microsoft.com/en-us/library/system.timers.timer.elapsed(v = vs.110).aspx) –

+0

为了让我的问题更清楚,如果让我们坐下来,方法需要59秒,然后休息一秒钟,然后重新开始。如果需要159秒,它可以运行,只要花费30秒就可以运行(或者我可以让它立即开始) – jjss

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(); 
} 
相关问题