我正在编写Windows服务,它会每隔几分钟处理一次“某事”。
以下是一些代码:
public Service()
{
this.InitializeComponent();
this.ServiceName = Name;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.eventLog.Source = Name;
// initialize timer
this.timer.Elapsed += this.TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
eventLog.WriteEntry("Starting syncronization...", EventLogEntryType.Information);
if (this.processor.PrepareToRun())
{
this.processor.Run();
}
}
我想知道如果this.processor.Run()
需要很长时间并且下一个TimerElapsed
事件会被提升会发生什么?它会跳过吗?完成后会等待并尽快运行吗?我应该考虑这些场景和代码吗?
我正在使用System.Timers.Timer
修改:
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
eventLog.WriteEntry("Starting syncronization...", EventLogEntryType.Information);
try
{
this.timer.Stop();
if (this.processor.PrepareToRun())
{
this.processor.Run();
}
}
catch (Exception ex)
{
LoggingAndNotifications.LogAndNotify(ex);
}
finally
{
this.timer.Start();
}
}
编辑2
public Service()
{
this.InitializeComponent();
this.ServiceName = Name;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.eventLog.Source = Name;
// initialize timer
this.timer.AutoReset = false;
this.timer.Elapsed += this.TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
eventLog.WriteEntry("Starting syncronization...", EventLogEntryType.Information);
try
{
if (this.processor.PrepareToRun())
{
this.processor.Run();
}
}
catch (Exception ex)
{
LoggingAndNotifications.LogAndNotify(ex);
throw;
}
finally
{
this.timer.Start();
}
}
答案 0 :(得分:14)
它会在另一个主题上再次调用它。
根据您要执行的操作的性质:
答案 1 :(得分:4)
如果我不希望后续的计时器激活在完成之前再次执行该方法,我会使用以下内容:
private void TimerFired(object sender, System.Timers.ElapsedEventArgs e) {
// only execute the code within this method if we are able to
// get a lock. This will ensure that any Timer firings will be
// ignored that occur while we're already doing work (OnTimer)
if (Monitor.TryEnter(lockObj)) {
try {
// do work here
} finally {
Monitor.Exit(lockObj);
}
}
}
否则,如果该方法的持续时间可能长于计时器间隔,则该方法可能会在第一个完成之前在另一个线程上开始执行。
答案 2 :(得分:3)
您可以看到此示例应用会发生什么:
class Program
{
static void Main(string[] args)
{
System.Timers.Timer timer = new System.Timers.Timer(2000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedObject);
timer.Start();
while (true)
{
}
}
static void OnTimedObject(object source, ElapsedEventArgs e)
{
Console.WriteLine("entered");
Thread.Sleep(3000);
Console.WriteLine("exited");
}
}
在“退出”首次出现之前,您会看到两个“已输入”的字符串显示出来。它会继续下去。所以线程不会互相踩到。
(顺便说一句,我不是在提倡无限循环。:))
答案 3 :(得分:2)
当引发计时器事件时,计划在线程池上执行计时器代码。最有可能它将在另一个线程中执行,但它取决于不同的因素(处理器数,线程利用率等)。然而它与计时器没有任何关系 - 它是线程池的职责。
我个人从不使用计时器间隔。我设置计时器运行一次,在我的代码执行后再次设置它。因此,我确保代码仅在单线程中执行。
答案 4 :(得分:0)
我这样做是为了处理这种情况。当然,您需要针对多线程操作等特殊情况进行调整。
public Service()
{
bool _IsProcessRunning = false;
this.InitializeComponent();
this.ServiceName = Name;
this.CanPauseAndContinue = true;
this.CanShutdown = true;
this.eventLog.Source = Name;
// initialize timer
this.timer.Elapsed += this.TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
if(!_IsProcessRunning)
{
DoSomething();
}
}
private void DoSomething()
{
try
{
_IsProcessRunning = true;
// Do our stuff here
}
catch(Exception Ex)
{
}
finally
{
_IsProcessRunning = false;
}
}
答案 5 :(得分:0)
执行时间超过span时的计时器行为?
当任务执行时间超过计时器时间跨度时。 TimerElapsed事件将被提升为一个新的线程。它不会被跳过。多线程实现到System.Timers.Timer