Почему мой компьютер с Windows 10 не просыпается после вызова SetWaitableTimer()?

У меня есть два компьютера с Windows 10, на которых установлено обновление Fall Creators, со всеми последними установленными исправлениями. Один просыпается из сна после того, как таймер установлен через CreateWaitableTimer/SetWaitableTimer, другой - нет... что является проблемой, потому что не пробуждающийся мой DVR и должен быть в состоянии проснуться по требованию:).

Также не включен режим гибернации.

Я не вижу никаких необычных событий в системе, которая отказывается просыпаться. Он просто не просыпается, если я не сделаю ручное пробуждение или не отправлю ему пакет пробуждения по локальной сети.

Вот тестовый код C#, который я запускаю на обеих системах:

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 );
}
}

Будем весьма благодарны за предложения о том, что проверять или какие дополнительные диагностические меры следует предпринять.

Дополнительная информация

Было предложено попробовать разбудить компьютер с помощью заданного вручную запланированного задания (т. Е. С помощью приложения Task Scheduler). Интересно, что задание не разбудило компьютер.

1 ответ

Решение

В процессе обновления для Fall Creators Update была изменена ключевая настройка управления питанием.

В разделе "Дополнительные параметры питания" -> "Режим сна" -> "Разрешить таймеры пробуждения" предыдущий параметр "Включить" был изменен на "Только важные таймеры пробуждения". "Только важные таймеры пробуждения" была введена сравнительно недавно.

Это изменение привело к тому, что система, которая не проснулась, проигнорировала события пробуждения, запланированные в программном обеспечении. По сути, он предназначен для того, чтобы учитывать только пробуждения операционной системы.

Возврат значения "Включено" решило проблему.

Другие вопросы по тегам