问题
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 :).
Neither has hibernation enabled.
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.
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.
Additional Info
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.
回答1:
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.
来源:https://stackoverflow.com/questions/47721696/why-isnt-my-windows-10-pc-waking-up-after-a-setwaitabletimer-call