本文介绍了为什么我的 Windows 10 PC 在 SetWaitableTimer() 调用后没有唤醒?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两台 Windows 10 PC,都运行 Fall Creators Update,并且安装了所有最近的补丁.通过 CreateWaitableTimer/SetWaitableTimer 设置定时器后,一个从睡眠中醒来,另一个没有......这是一个问题,因为未唤醒的一个是我的 DVR,需要能够按需唤醒:).

I have two Windows 10 PCs, both running the Fall Creators Update, with all recent patches installed. One wakes up from sleep after a timer is set via CreateWaitableTimer/SetWaitableTimer, the other doesn't...which is a problem, because the non-waking one is my DVR and needs to be able to wake up on demand :).

均未启用休眠.

我在系统上看不到任何拒绝唤醒的异常事件.它只是不会唤醒,除非我手动唤醒或向它发送网络唤醒数据包.

I can't see any unusual events on the system which refuses to wake up. It just doesn't wake up, unless I do a manual wakeup or send it a wake-on-lan packet.

这是我在两个系统上运行的 C# 测试代码:

Here's the C# test code I'm running on both systems:

public class Program
{
[ DllImport( "kernel32.dll" ) ]
private static extern SafeWaitHandle CreateWaitableTimer( IntPtr lpTimerAttributes, bool bManualReset,
    string lpTimerName );

[ DllImport( "kernel32.dll", SetLastError = true ) ]
[ return : MarshalAs( UnmanagedType.Bool ) ]
private static extern bool SetWaitableTimer( SafeWaitHandle hTimer, [ In ] ref long pDueTime, int lPeriod,
    IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume );

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CancelWaitableTimer(IntPtr hTimer);

[DllImport("powrprof.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);

private static ILogger _logger;

private static bool Hibernate()
{
    bool retVal = SetSuspendState(true, false, false);

    _logger.Information(retVal
        ? $"Returning from hibernation at {DateTime.Now.ToLongTimeString()}"
        : $"Failed to enter hibernation, error message was {Marshal.GetLastWin32Error()}");

    return retVal;
}

private static bool Sleep()
{
    bool retVal = SetSuspendState(false, false, false);

    _logger.Information( retVal
        ? $"Returning from sleep at {DateTime.Now.ToLongTimeString()}"
        : $"Failed to enter sleep, error message was {Marshal.GetLastWin32Error()}" );

    return retVal;
}

private static void SetWakeTimer( int minutes, bool hibernate )
{
    DateTime utc = DateTime.Now.AddMinutes( minutes );
    long duetime = utc.ToFileTime();

    using( SafeWaitHandle handle = CreateWaitableTimer( IntPtr.Zero, true, "SleepWakeTimerTest" ) )
    {
        if( SetWaitableTimer( handle, ref duetime, 0, IntPtr.Zero, IntPtr.Zero, true ) )
        {
            _logger.Information($"Timer set, will trigger at {utc.ToLongTimeString()}");

            if ( hibernate ) Hibernate();
            else Sleep();
        }
        else
            Console.WriteLine($"CreateWaitableTimer failed, error message was {Marshal.GetLastWin32Error()}");
    }
}

static void Main( string[] args )
{
    _logger = new LoggerConfiguration()
        .WriteTo.File( $"log-{DateTime.Now:yyyy-M-d-hhmmss}.txt" )
        .CreateLogger();

    _logger.Information("parsing command line arguments...");

    var cmdLine = new FluentCommandLineParser();

    int delay = 2;
    bool hibernate = false;

    cmdLine.Setup<int>( 'd', "delay" )
        .Callback( x => delay = x )
        .SetDefault( 2 )
        .WithDescription( "wakeup delay, in minutes" );

    cmdLine.Setup<bool>( 'h', "hibernate" )
        .Callback( x => hibernate = x )
        .SetDefault( false )
        .WithDescription( "hibernate if flag set, otherwise sleep" );

    SetWakeTimer( delay, hibernate );
}
}

非常感谢您提供有关检查内容或采取哪些额外诊断步骤的建议.

Suggestions on what to check or what additional diagnostic steps to take would be much appreciated.

附加信息

有人建议我尝试通过手动定义的计划任务(即使用任务计划程序应用程序)唤醒计算机.有趣的是,任务并没有唤醒计算机.

It was suggested that I try waking the computer via a manually-defined scheduled task (i.e., by using the Task Scheduler app). Interestingly, the task did not wake up the computer.

推荐答案

在秋季创意者更新的升级过程中,一个关键的电源管理设置发生了变化.

During the upgrade process for the Fall Creators Update, a key power management setting got changed.

在高级电源设置 -> 睡眠 -> 允许唤醒定时器下,之前的启用设置更改为仅重要唤醒定时器.仅限重要唤醒计时器"是最近推出的一项新设置.

Under Advanced Power Settings -> Sleep -> Allow Wake Timers, the previous setting of Enable got changed to Important Wake Timers Only. "Important Wake Timers Only" was a new setting introduced relatively recently.

此更改导致无法唤醒的系统忽略软件中安排的唤醒事件.基本上,它旨在仅允许操作系统唤醒.

This change caused the system which was failing to wake up to ignore wake up events scheduled in software. Basically, it's designed to allow only operating system wake ups to be honored.

将设置恢复为启用解决了问题.

Reverting the setting to Enabled solved the problem.

这篇关于为什么我的 Windows 10 PC 在 SetWaitableTimer() 调用后没有唤醒?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 02:01