【问题标题】:Why does C# Timer Restarts When I Change Interval in Elapsed function为什么当我在 Elapsed 函数中更改间隔时 C# Timer 会重新启动
【发布时间】:2020-07-08 12:04:41
【问题描述】:

我正在使用System.Timers.Timer 类,我想在已用函数中将其更改为Interval。当我将Elapsed 属性设置为不同的值时,不知何故,经过的函数开始触发并再次触发,尽管计时器的Autoreset 属性设置为false。

我的代码:

            var timer = new Timer()
            {
                Interval = 1000,
                AutoReset = false,
            };

            timer.Enabled = true;
        
            timer.Elapsed += (sender, eventArgs) =>
            {
                Console.WriteLine("Timer fires");
                timer.Interval = 2000;
            };

当我只是想更改计时器的后续使用间隔时,代码会一次又一次地触发计时器。

很高兴知道为什么会发生这种情况以及我应该怎么做才能实现所需的行为。

【问题讨论】:

  • 这是设计使然:MSDN如果在计时器启动后设置间隔,则重置计数。例如,如果您将时间间隔设置为 5 秒,然后将 Enabled 属性设置为 true,则在设置 Enabled 时开始计数。如果在 count 为 3 秒时将间隔重置为 10 秒,则在 Enabled 设置为 true 13 秒后第一次引发 Elapsed 事件。 - 您可以尝试使用第二个计时器来解决问题..跨度>

标签: c# events timer elapsed


【解决方案1】:

Timer.Close 将释放与此计时器对象关联的所有资源,这似乎有所帮助。

在 Elapsed 事件处理程序逻辑中,当 Timer.Interval 设置为大于零的数字时,表示再次调用“Elapsed”事件,整个逻辑进入无限循环。

static void Main(string[] args)
{
    var timer = new Timer()
    {
        Interval = 1000,
        AutoReset = false,
    };

    timer.Enabled = true;
    timer.Elapsed += (sender, eventArgs) =>
    {
        Console.WriteLine("Timer fires Elapsed = " + timer.Interval.ToString());
        timer.Close();
        timer.Interval = 800;
    };
    Console.WriteLine("The timer event should have fired just once. Press the Enter key to resume ");
    Console.ReadLine();

    // Again enable the timer to make sure it fires the elapsed event after 800 ms
    timer.Enabled = true;
    Console.WriteLine("Press the Enter key to resume ");
    Console.ReadLine();

    // Overwrite the earlier time interval to 200 ms.
    timer.Interval = 200;
    timer.Enabled = true;
    Console.WriteLine("Press the Enter key to resume ");
    Console.ReadLine();
            
    timer.Enabled = true;
    Console.WriteLine("Press the Enter key to exit the program at any time... ");
    Console.ReadLine();
}

【讨论】:

    【解决方案2】:

    我不知道为什么在您更改间隔后计时器会再次启动,但这里有一个解决此问题的方法。

    timer.Elapsed += (sender, eventArgs) =>
    {
        Console.WriteLine("Timer fires");
        timer = new Timer()
        {
            Interval = 2000,
            AutoReset = false,
        };
    };
    

    您也可以使用 DispatcherTimer。

    var dt = new DispatcherTimer();
    
    dt.Interval = new TimeSpan(0, 0, 1);
    
    dt.Tick += (sender, eventArgs) =>
    {
        dt.Stop();
        dt.Interval = new TimeSpan(0, 0, 2);
    };
    

    编辑: 经过一些测试,我找到了更好的解决方法。

    如果您再次启动计时器而不是更改间隔并立即再次停止它,那么它似乎可以工作。

    timer.Elapsed += (sender, eventArgs) =>
    {
        Console.WriteLine("Timer fires");
        timer.Enabled = true;
        timer.Interval = 2000;
        timer.Enabled = false;
    };
    

    【讨论】:

    • 感谢您的回答。我正在考虑在这里使用第一个选项,但我不想每次触发 Elapsed 事件时都创建新对象。至于第二种方法,我特别想使用System.Timers.Timer,因为它使用自己的线程池并且异步运行。
    • 是的,我也不认为这是一个好的解决方案。但也许我的新的第三种方法更适合你。
    猜你喜欢
    • 2011-11-23
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多