System.Timers.Timer 在 WPF 应用程序中的行为如何,在休眠和睡眠之后? [英] How System.Timers.Timer behave in WPF application, after Hibernate, and Sleep?

查看:47
本文介绍了System.Timers.Timer 在 WPF 应用程序中的行为如何,在休眠和睡眠之后?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 WPF 应用程序中使用 System.Timers.Timer.我想了解 Timer 在计算机休眠和睡眠后的行为方式.在计算机从休眠状态恢复后,我的应用程序出现了一些奇怪的问题.

我应该如何处理定时器,以及当计算机处于休眠/睡眠模式时它们的行为如何?

我有一个午夜计时器,它应该在每个午夜工作以重置 UI 上的默认值.

这是创建计时器的代码:

private void ResetMidnightTimer(){//杀死旧计时器DisposeMidnightTimer();_midnightTimer = 新定时器();//将计时器安排在午夜后 1 分钟_midnightTimer.Interval = (DateTime.Today.AddDays(1).AddMinutes(1) - DateTime.Now).TotalMilliseconds;_midnightTimer.Elapsed += (_, __) =>UpdateRecommendedCollectingTime();_midnightTimer.Enabled = true;_midnightTimer.Start();}

在 UI 页面的构造函数中,我调用了调用 ResestMidnightTimer() 的方法并创建了事实上的计时器.之后,计时器就等待夜晚.

当夜间时间(实际上是凌晨 12:01)到来时,计时器开始工作,按预期重置默认值,然后处理现有计时器.最后,它为第二天创建一个新的午夜计时器.但是,如果我在那天尝试使计算机休眠,则午夜计时器将不起作用,也不会重置默认值.

是不是因为在休眠时它只是将事件处理推迟了与休眠相同的时间?

解决方案

这取决于您如何使用计时器.如果您使用它们来启动一些不经常发生的事件(超过几分钟),那么您可能会看到一些奇怪"的行为.由于您没有指定这种奇怪"的行为是什么,我将假设您的程序的计时器比它应该的时间更晚.

说明:进入睡眠/休眠状态的问题是所有程序都被挂起.这意味着您的计时器没有更新,因此当您睡觉/休眠并回来时,就好像您在睡觉/休眠的那段时间里被冻结了.这意味着,如果您将计时器设置为一小时后关闭,并且您的计算机在 15 分钟标记处进入睡眠状态,那么一旦它醒来,无论计算机睡眠多长时间,它都会再有 45 分钟的时间.

解决方案:一种解决方法是将 DateTime 保留在上次发生事件的时间附近.然后,让计时器定期(每 10 秒或 10 分钟,取决于所需的精度)并检查上次执行的日期时间.如果现在和上次执行时间之间的差异大于或等于所需的时间间隔,则运行执行.

这将修复它,以便如果在睡眠/休眠期间应该"发生事件,它将在您从睡眠/休眠状态返回的那一刻开始.

更新:上面提供的解决方案将起作用,我将填写一些详细信息以帮助您实施它.

  • 不是创建/处理新的计时器,而是创建 ONE 个计时器以使用 RECURRING(AutoReset 属性设置为 true)

  • 单次定时器的间隔应该根据下一次事件发生的时间来设置.相反,它应该设置为您选择的一个值来表示轮询频率(它检查事件"是否应该运行的频率).选择应该是效率和精度的平衡.如果您需要它在接近凌晨 12:01 运行,那么您可以将间隔设置为大约 5-10 秒.如果恰好在凌晨 12:01 不那么重要,您可以将时间间隔增加到 1-10 分钟之类的时间.

  • 您需要保留上次执行发生的日期时间OR,下次执行应该发生的时间.我更喜欢何时应该执行下一次执行",这样您就不会在每次计时器过去时都执行 (LastExecutionTime + EventInterval),您只需比较当前时间和事件应该发生的时间.

  • 一旦计时器结束并且事件应该发生(大约在凌晨 12:01 左右),您应该更新存储的 DateTime,然后运行您想要在凌晨 12:01 运行的代码.

睡眠与休眠的说明:睡眠和休眠之间的主要区别在于,在睡眠中,所有内容都保存在 RAM 中,而休眠将当前状态保存到磁盘.休眠的主要优点是 RAM 不再需要电源,因此消耗的能量更少.这就是为什么在处理使用有限能量的笔记本电脑或其他设备时建议使用休眠而不是睡眠的原因.

也就是说,程序的执行没有区别,因为它们在任何一种情况下都被挂起.不幸的是,System.Timers.Timer 不会唤醒"计算机,因此您无法强制您的代码在大约凌晨 12:01 运行.

我相信还有其他方法可以唤醒"计算机,但除非你走那条路,否则你能做的最好的事情就是在你的计时器从睡眠中出来后的下一个轮询事件"期间运行你的事件"/休眠.

I'm using System.Timers.Timer in my WPF application. I want to understand how Timer does behave, after Computer is hibernated, and sleep. I'm getting some weird issues with my application, after computer is getting resumed from hibernate.

How should I handle timers, and how do they behave when computer is in hibernate/sleep mode?

I have a midnight timer which should work each midnight to reset the default values on UI.

Here is the code that creates the timer:

private void ResetMidnightTimer() 
        { 
            // kill the old timer
            DisposeMidnightTimer();

            _midnightTimer = new Timer();
            // scheduling the timer to elapse 1 minute after midnight
            _midnightTimer.Interval = (DateTime.Today.AddDays(1).AddMinutes(1) - DateTime.Now).TotalMilliseconds;
            _midnightTimer.Elapsed += (_, __) => UpdateRecommendedCollectingTime();
            _midnightTimer.Enabled = true;
            _midnightTimer.Start();
        }

On UI page's contructor, I call the method which calls ResestMidnightTimer() and creates the timer de facto. After that the timer just waits for the night.

When the night time (actually it is the 12:01 AM) comes, the timer works, resets the default values as expected and then disposes existing timer. Finally it creates a new midnight timer for next day. But if I try to hibernate the computer during that day, the midnight timer won't work and won't reset the default values.

Is that because while hibernating it just postpones the event handling by the same amount of time it was hibernated?

解决方案

This depends on how you are using your timers. If you are using them to initiate some event that occurs infrequently (greater than a couple minutes) then you will probably see some 'weird' behavior. Since you don't specify what that 'weird' behavior is, I'm going to assume that your program's timer goes off later than it should.

Explanation: The problem with going to sleep/hibernating is that all programs are suspended. This means that your Timers are not being updated and thus when you sleep/hibernate and come back, it is as if you were frozen for that period of time that you were sleeping/hibernating. This means if you have a timer set to go off in an hour and your computer goes to sleep at the 15 minute mark, once it wakes up it will have another 45 minutes to go, regardless of how long the computer was sleeping.

Solution: One fix would be to keep a DateTime around of the last time the event occurred. Then, have a timer go off periodically (every 10 seconds or 10 minutes, depending on the precision desired) and check the DateTime of the last execution. If the difference between now and the last execution time is greater than or equal to the interval desired, THEN you run execution.

This will fix it so that if an event 'should have' occurred during sleeping/hibernating, it will start the moment you return from sleeping/hibernating.

Update: The solution presented above will work and I'll fill in a couple of details to help you implement it.

  • Instead of creating/disposing of new Timers, create ONE timer to use that is RECURRING (the AutoReset property is set to true)

  • The interval of the single timer should NOT be set according to the next time the event should occur. Instead, it should be set to a value you choose that will represent the polling frequency (how often it checks to see if the 'event' should run). The choice should be a balance of efficiency and precision. If you NEED it to run REALLY close to 12:01 AM then you set the interval to around 5-10 seconds. If it is less important that it be at exactly 12:01 AM, you can increase the interval to something like 1-10 minutes.

  • You need to keep around a DateTime of when the last execution occurred OR when the next execution should happen. I would prefer 'when the next execution should happen' so that you aren't doing (LastExecutionTime + EventInterval) each time the timer elapses, you'll just be comparing the current time and the time the event should occur.

  • Once the timer elapses and the event SHOULD occur (somewhere around 12:01 AM), you should update the stored DateTime and then run the code you want run at 12:01 AM.

Sleep vs. Hibernate Clarification: The main difference between sleep and hibernate is that in sleep, everything is kept in RAM whereas hibernate saves the current state to disk. The main advantage of hibernate is that the RAM no longer needs power and thus expends less energy. This is why it is recommended to use hibernate over sleep when dealing with laptops or other devices using a finite amount of energy.

That said, there is no difference in the execution of programs as they are being suspended in either case. Unfortunately, the System.Timers.Timer does not 'wake up' a computer and so you can't enforce your code to be run at ~12:01 AM.

I believe there are OTHER ways to 'wake up' a computer but unless you go that route the best you can do is run your 'event' during the next 'polling event' of your timer after it comes out of sleep/hibernate.

这篇关于System.Timers.Timer 在 WPF 应用程序中的行为如何,在休眠和睡眠之后?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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