Skip to content

Commit

Permalink
Proper threading support for all parts of the keep-awake process
Browse files Browse the repository at this point in the history
  • Loading branch information
dend committed May 12, 2021
1 parent a78da90 commit 3d8ed39
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 46 deletions.
60 changes: 46 additions & 14 deletions src/modules/espresso/Espresso/Core/APIHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,14 @@ public static bool SetNormalKeepAwake()
return SetAwakeState(EXECUTION_STATE.ES_CONTINUOUS);
}

/// <summary>
/// Sets up the machine to be awake indefinitely.
/// </summary>
/// <param name="keepDisplayOn">Determines whether the display should be kept on while the machine is awake.</param>
/// <returns>Status of the attempt. True if successful, false if not.</returns>
public static bool SetIndefiniteKeepAwake(bool keepDisplayOn = true)
public static void SetIndefiniteKeepAwake(Action<bool> callback, Action failureCallback, bool keepDisplayOn = true)
{
if (keepDisplayOn)
{
return SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}
else
{
return SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}
_tokenSource = new CancellationTokenSource();
_threadToken = _tokenSource.Token;

Task.Run(() => RunIndefiniteLoop(keepDisplayOn), _threadToken)
.ContinueWith((result) => callback(result.Result), TaskContinuationOptions.OnlyOnRanToCompletion)
.ContinueWith((result) => failureCallback, TaskContinuationOptions.NotOnRanToCompletion);
}

public static void SetTimedKeepAwake(long seconds, Action<bool> callback, Action failureCallback, bool keepDisplayOn = true)
Expand All @@ -105,6 +98,45 @@ public static void SetTimedKeepAwake(long seconds, Action<bool> callback, Action
.ContinueWith((result) => failureCallback, TaskContinuationOptions.NotOnRanToCompletion);
}

private static bool RunIndefiniteLoop(bool keepDisplayOn = true)
{
bool success;
if (keepDisplayOn)
{
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}
else
{
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}

try
{
if (success)
{
_log.Info("Initiated indefinite keep awake in background thread.");
while (true)
{
if (_threadToken.IsCancellationRequested)
{
_threadToken.ThrowIfCancellationRequested();
}
}
}
else
{
_log.Info("Could not successfully set up indefinite keep awake.");
return success;
}
}
catch (OperationCanceledException ex)
{
// Task was clearly cancelled.
_log.Info($"Background thread termination. Message: {ex.Message}");
return success;
}
}

private static bool RunTimedLoop(long seconds, bool keepDisplayOn = true)
{
bool success = false;
Expand Down
40 changes: 8 additions & 32 deletions src/modules/espresso/Espresso/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,38 +186,29 @@ private static void HandleCommandLineArguments(bool usePtConfig, bool displayOn,
}
}

var exitSignal = new ManualResetEvent(false);
if (pid != 0)
{
RunnerHelper.WaitForPowerToysRunner(pid, () =>
{
exitSignal.Set();
Environment.Exit(0);
});
}

new ManualResetEvent(false).WaitOne();
exitSignal.WaitOne();
}

private static void SetupIndefiniteKeepAwake(bool displayOn)
{
// Indefinite keep awake.
bool success = APIHelper.SetIndefiniteKeepAwake(displayOn);
if (success)
{
_log.Info($"Currently in indefinite keep awake. Display always on: {displayOn}");
}
else
{
var errorMessage = "Could not set up the state to be indefinite keep awake.";
_log.Info(errorMessage);
_log.Debug(errorMessage);
}
APIHelper.SetIndefiniteKeepAwake(LogCompletedKeepAwakeThread, LogUnexpectedOrCancelledKeepAwakeThreadCompletion, displayOn);
}

private static void HandleEspressoConfigChange(FileSystemEventArgs fileEvent)
{
_log.Info("Detected a settings file change. Updating configuration...");
_log.Info("Resetting keep-awake to normal state due to settings change.");
ResetNormalPowerState();
ProcessSettings();
}

Expand Down Expand Up @@ -277,34 +268,19 @@ private static void SetupTimedKeepAwake(long time, bool displayOn)
{
_log.Info($"Timed keep-awake. Expected runtime: {time} seconds with display on setting set to {displayOn}.");

APIHelper.SetTimedKeepAwake(time, LogTimedKeepAwakeCompletion, LogUnexpectedOrCancelledKeepAwakeCompletion, displayOn);
APIHelper.SetTimedKeepAwake(time, LogCompletedKeepAwakeThread, LogUnexpectedOrCancelledKeepAwakeThreadCompletion, displayOn);
}

private static void LogUnexpectedOrCancelledKeepAwakeCompletion()
private static void LogUnexpectedOrCancelledKeepAwakeThreadCompletion()
{
var errorMessage = "The keep-awake thread was terminated early.";
_log.Info(errorMessage);
_log.Debug(errorMessage);
}

private static void LogTimedKeepAwakeCompletion(bool result)
private static void LogCompletedKeepAwakeThread(bool result)
{
_log.Info($"Completed timed keep-awake successfully: {result}");
}

private static void ResetNormalPowerState()
{
bool success = APIHelper.SetNormalKeepAwake();
if (success)
{
_log.Info("Returned to normal keep-awake state.");
}
else
{
var errorMessage = "Could not return to normal keep-awake state.";
_log.Info(errorMessage);
_log.Debug(errorMessage);
}
_log.Info($"Exited keep-awake thread successfully: {result}");
}
}
}

0 comments on commit 3d8ed39

Please sign in to comment.