【问题标题】:Detect when C# app has gone to sleep (SystemEvents.PowerModeChanged not being called)检测 C# 应用程序何时进入睡眠状态(未调用 SystemEvents.PowerModeChanged)
【发布时间】:2020-10-15 16:49:43
【问题描述】:

PowerModeChanged 事件似乎有问题(关于它的许多问题),但我找到的答案都没有帮助我。

我有一个运行 .NET Core 3.1 的 C#/WPF Windows 客户端应用程序(不是服务,没有什么花哨的,只是一个普通的 GUI 桌面应用程序)。我有一些事情发生在计时器上,我需要知道我什么时候错过了一个或两个计时器,因为笔记本电脑进入了睡眠状态(或暂停或其他任何事情)。

这是我的主窗口中的内容,我正在抓取我能找到的每一个事件:

private void OnLoaded(object sender, RoutedEventArgs e)
{
    DispatcherTimer timer = new DispatcherTimer();
    timer.Tick += (a, b) => LiveTimer();
    timer.Interval = new TimeSpan(0, 0, 10);
    timer.Start();

    SystemEvents.PowerModeChanged += OnPowerModeChanged;
    SystemEvents.SessionSwitch += OnSessionSwitch;
}

protected override void OnDeactivated(EventArgs e)
{
    Debug.WriteLine("MainWindow.OnDeactivated()");
    Log.Info(this, "Main window deactivated");
    base.OnDeactivated(e);
}

protected override void OnStateChanged(EventArgs e)
{
    Debug.WriteLine("MainWindow.OnStateChanged()");
    Log.Info(this, "Main window state changed [WindowState=" + WindowState + "]");
    base.OnStateChanged(e);
}

private void OnSessionSwitch(object sender, SessionSwitchEventArgs e)
{
    Debug.WriteLine("MainWindow.OnSessionSwitch(sender=" + sender + ", e [Reason=" + e.Reason + "])");
    Log.Info(this, "Session switched because " + e.Reason);
}

private void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
    Debug.WriteLine("MainWindow.OnPowerModeChanged(sender=" + sender + ", e [Mode=" + e.Mode + "])");
    Log.Info(this, "Power mode changed to " + e.Mode);
}

private void LiveTimer()
{
   Debug.WriteLine("MainWindow.LiveTimer() at " + DateTime.Now.ToString("HH:mm:ss.fff"));
}

因此,如果我在笔记本电脑上运行此应用程序并等待屏幕锁定(5 分钟)并等待笔记本电脑进入睡眠状态(10 分钟),我会在调试控制台中看到以下内容:

MainWindow.LiveTimer() at 10:07:17.711
(this happens every 10 seconds)
MainWindow.LiveTimer() at 10:12:20.593

MainWindow.OnSessionSwitch(sender=Microsoft.Win32.SystemEvents, e [Reason=SessionLock])

MainWindow.LiveTimer() at 10:12:30.614
(this happens every 10 seconds)
MainWindow.LiveTimer() at 10:17:24.173

(and now it goes to sleep)
(and then I wake it up)

MainWindow.LiveTimer() at 10:31:28.519

MainWindow.OnSessionSwitch(sender=Microsoft.Win32.SystemEvents, e [Reason=SessionUnlock])

MainWindow.LiveTimer() at 10:31:38.716
(and now we're back to firing every 10 seconds)

基本上,我绝对不会收到关于笔记本电脑要进入睡眠状态的任何通知,而且我暂时不会收到计时器消息。

我的应用如何发现它已经进入睡眠状态并被重新唤醒?

【问题讨论】:

    标签: c# wpf .net-core sleep-mode


    【解决方案1】:

    如果您只是想测量当前运行与上次运行之间的时间差,您是否有理由需要确定计算机何时休眠、何时唤醒等?

    即难道你不能只计算现在和上一次运行之间的时间差,每当计时器运行开始时?

    伪代码:

    private DateTime? previousRunTimestamp;
    
    private void TimerTick()
    {
        var now = DateTime.Now;
        var elapsedTimeSinceLastRun = previousRunTimestamp.HasValue ? now - previousRunTimestamp.Value : TimeSpan.Zero;
        previousRunTimestamp = now;
        
        const int secondsBetweenRuns = 10;
        var numberOfRunsMissed = (int)Math.Floor(elapsedTimeSinceLastRun.TotalSeconds / secondsBetweenRuns);
    
        // Do something about it when numberOfRunsMissed > 0
    
        // ...
    }
    

    【讨论】:

    • 这就是我开始实现的,问题是我在应用程序的各个地方都有一次性计时器,我怀疑那些根本不会触发(现在正在运行测试)。所以我必须让主窗口注意到丢失的时间,触发一个事件,现在我有一些函数(一些在库中)必须以某种方式接收该事件。我只是希望有更简单的东西。
    • 也许你可以有一个单独的计时器,每秒运行一次来​​管理/强制执行其他计时器(?)
    猜你喜欢
    • 2018-12-23
    • 2015-02-12
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 2022-07-09
    • 1970-01-01
    相关资源
    最近更新 更多