多个计时器已过的问题 [英] Multiple timer elapsed issue

查看:145
本文介绍了多个计时器已过的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个如下定义的计时器.计时器执行长时间运行的任务.我的问题是,当计时器运行时,间隔又过去了,另一个计时器开始执行,即_timer_Elapsed.计时器结束后,如何才能使计时器执行一个间隔.现在的方式是一次可以执行多个计时器,这会导致我的代码出现各种问题.

I have a timer as defined below. The timer executes a long running task. The problem i have is when the timer is running the interval has elapsed again and another timer execution starts i.e _timer_Elapsed. How can i get the timer to execute one interval after the timer has finished. The way it is now there could be multiple timer executions happening at once and that causes all sorts of issues with my code.

protected override void OnStart(string[] args)
        {

           _timer = new System.Timers.Timer();
           _timer.AutoReset = false;
           _timer.Interval = (Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"]));
           _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
           _timer.Enabled = true;
           _timer.Start(); // Start timer 

        }


 public static void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            try
            {
                _timer.Interval = (Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"])); 

                BLLGenericResult SystemCheckItems_Result = ServiceItemOperations.CheckItems(); // Long Running Task

            }
            catch (Exception ex)
            {
                // Exception handling...
            }
            finally
            {
                _timer.Start();
            }
        }

推荐答案

让我们正确地编写一下.间隔分配使您陷入麻烦.一个演示该问题的示例程序:

Let's properly write this up. It is the Interval assignment that is getting you into trouble. A sample program that demonstrates the issue:

using System;

class Program {
    static System.Timers.Timer timer;
    static void Main(string[] args) {
        timer = new System.Timers.Timer();
        timer.AutoReset = false;
        timer.Interval = 1000;
        timer.Elapsed += timer_Elapsed;
        timer.Start();
        Console.ReadLine();
    }

    static void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
        timer.Interval = 1000;
        Console.WriteLine("Tick");
    }
}

输出:

Tick
Tick
Tick
...

在Elapsed事件处理程序中删除时间间隔"分配以查看区别.

Remove the Interval assignment in the Elapsed event handler to see the difference.

因此,换句话说,即使AutoReset属性为 false ,仅分配Interval属性也足以使计时器重新启动.当然,令人惊讶的是,没有人看到这种情况的到来.它对您的程序造成了破坏,因为您在之前尽早分配了Interval属性,因此开始进行繁重的工作.因此,Elapsed事件将在另一个线程上再次引发,而您先前的事件尚未完成运行.那是一个正在等待发生的线程错误,尤其是在您的Interval值太小时的情况下.您稍后需要分配它,在 finally 块中进行分配.太好了,您使时间间隔太小了,以后很难诊断.

So, in other words, even though the AutoReset property is false, just assigning the Interval property is enough to get the timer to restart. Big surprise of course, nobody ever sees that coming. And it plays havoc on your program because you assign the Interval property early, before you start doing the heavy lifting. So the Elapsed event will be raised again, on another thread, while your previous one hasn't completed running yet. That's a threading bug waiting to happen, particularly if your Interval value is too small. You'll need to assign it later, do so inside the finally block. Good thing that you made the Interval too small, very hard to diagnose later.

这是C#错误吗?

is this a c# bug ?

C#语言不可用,这是一个.NET Framework错误.通常,System.Timers.Timer并不是一个很好的类,它具有无需安全开关即可使用的链锯.这是为了使System.Threading.Timer类更可用,尤其是解决了过早收集垃圾的习惯的问题.解决了一个问题,但增加了三个新问题.这可以追溯到.NET 1.0,这是带有训练轮的框架版本.他们只是无法修复它,太多的现有代码将中断.使用System.Threading.Timer确实更好,只需确保将引用的对象保留在变量中即可.就像你已经做过一样.

The C# language is off the hook, this is a .NET Framework bug. System.Timers.Timer is in general just not a very good class, it has the usability of a chainsaw without a safety switch. It was meant to make the System.Threading.Timer class more usable, in particular solving a problem with the habit of it being garbage collected too soon. One problem solved, but three new problems added. This goes back to .NET 1.0, a framework version with training wheels. They just can't fix it anymore, too much existing code will break. You really are better off with the System.Threading.Timer, just make sure to keep the object referenced in a variable. Like you already do.

这篇关于多个计时器已过的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆