private void ThreadExecution(CancellationToken cancellationToken) { try { _state.Value = PatcherState.None; DebugLogger.Log("Patcher thread started."); ThreadLoadPatcherData(); EnsureSingleInstance(); ThreadLoadPatcherConfiguration(); UnityDispatcher.Invoke(() => _app = new App(_data.Value.AppDataPath, _data.Value.AppSecret, _data.Value.OverrideLatestVersionId)).WaitOne(); while (true) { cancellationToken.ThrowIfCancellationRequested(); ThreadWaitForUserDecision(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); ThreadExecuteUserDecision(cancellationToken); } } catch (OperationCanceledException) { DebugLogger.Log("Patcher thread finished: thread has been cancelled."); } catch (ThreadInterruptedException) { DebugLogger.Log("Patcher thread finished: thread has been interrupted."); } catch (ThreadAbortException) { DebugLogger.Log("Patcher thread finished: thread has been aborted."); } catch (MultipleInstancesException exception) { DebugLogger.LogException(exception); Quit(); } catch (Exception exception) { DebugLogger.LogError("Patcher thread failed: an exception has occured."); DebugLogger.LogException(exception); } finally { _state.Value = PatcherState.None; if (_app != null) { _app.Dispose(); _app = null; } } }
/// <summary> /// Like Thread.Sleep() but checks if cancelation occured meanwhile /// </summary> /// <param name="duration">Miliseconds, time to sleep</param> /// <param name="cancellationToken">token to check cancellation exception</param> public static void CancelableSleep(int duration, PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken) { // FIX: Bug #692 int singleSleep = 100; for (int i = 0; i < duration / singleSleep; ++i) { cancellationToken.ThrowIfCancellationRequested(); Thread.Sleep(singleSleep); } }
protected void Display(PatchKit.Unity.Patcher.Cancellation.CancellationToken cancellationToken) { Assert.IsFalse(_unityThread == Thread.CurrentThread, "Display dialog can be only used on separate thread."); try { _isDisplaying = true; _dialogDisplayed.Reset(); using (cancellationToken.Register(() => _dialogDisplayed.Set())) { cancellationToken.ThrowIfCancellationRequested(); _dialogDisplayed.WaitOne(); } } finally { _isDisplaying = false; } }
private void ThreadWaitForUserDecision(CancellationToken cancellationToken) { try { DebugLogger.Log("Waiting for user decision..."); _state.Value = PatcherState.WaitingForUserDecision; bool isInstalled = _app.IsFullyInstalled(); DebugLogger.LogVariable(isInstalled, "isInstalled"); bool canRepairApp = false; // not implemented bool canInstallApp = !isInstalled; bool canCheckForAppUpdates = isInstalled; bool canStartApp = isInstalled; _isAppInstalled.Value = isInstalled; _canRepairApp.Value = false; _canInstallApp.Value = false; _canCheckForAppUpdates.Value = false; _canStartApp.Value = false; if (canInstallApp && _configuration.AutomaticallyInstallApp && !_hasAutomaticallyInstalledApp) { DebugLogger.Log("Automatically deciding to install app."); _hasAutomaticallyInstalledApp = true; _hasAutomaticallyCheckedForAppUpdate = true; _userDecision = UserDecision.InstallAppAutomatically; return; } if (canCheckForAppUpdates && _configuration.AutomaticallyCheckForAppUpdates && !_hasAutomaticallyCheckedForAppUpdate) { DebugLogger.Log("Automatically deciding to check for app updates."); _hasAutomaticallyInstalledApp = true; _hasAutomaticallyCheckedForAppUpdate = true; _userDecision = UserDecision.CheckForAppUpdatesAutomatically; return; } var updatesOnly = Environment.GetCommandLineArgs().Any(arg => arg.Equals("--updateOnly", StringComparison.OrdinalIgnoreCase)); if (canStartApp && updatesOnly) { _canStartApp.Value = true; _userDecision = UserDecision.AppUpdatesOnly; return; } else { if (canStartApp && _configuration.AutomaticallyStartApp && !_hasAutomaticallyStartedApp) { DebugLogger.Log("Automatically deciding to start app."); _hasAutomaticallyStartedApp = true; _userDecision = UserDecision.StartAppAutomatically; return; } _canRepairApp.Value = canRepairApp; _canInstallApp.Value = canInstallApp; _canCheckForAppUpdates.Value = canCheckForAppUpdates; _canStartApp.Value = canStartApp; } _userDecisionSetEvent.Reset(); using (cancellationToken.Register(() => _userDecisionSetEvent.Set())) { cancellationToken.ThrowIfCancellationRequested(); _userDecisionSetEvent.WaitOne(); } _canRepairApp.Value = false; _canInstallApp.Value = false; _canCheckForAppUpdates.Value = false; _canStartApp.Value = false; cancellationToken.ThrowIfCancellationRequested(); DebugLogger.Log(string.Format("Waiting for user decision result: {0}.", _userDecision)); } catch (OperationCanceledException) { DebugLogger.Log("Waiting for user decision cancelled."); } catch (ThreadInterruptedException) { DebugLogger.Log("Waiting for user decision interrupted: thread has been interrupted. Rethrowing exception."); throw; } catch (ThreadAbortException) { DebugLogger.Log("Waiting for user decision aborted: thread has been aborted. Rethrowing exception."); throw; } catch (Exception) { DebugLogger.LogWarning("Error while waiting for user decision: an exception has occured. Rethrowing exception."); throw; } }
private void ThreadExecution(CancellationToken cancellationToken) { try { _state.Value = PatcherState.None; DebugLogger.Log("Patcher thread started."); try { ThreadLoadPatcherData(); } catch (NonLauncherExecutionException) { try { LauncherUtilities.ExecuteLauncher(); return; } catch (ApplicationException) { ThreadDisplayError(PatcherErrorMessage.NonLauncherExecution(), cancellationToken); return; } finally { Quit(); } } EnsureSingleInstance(); ThreadLoadPatcherConfiguration(); UnityDispatcher.Invoke(() => _app = new App(_data.Value.AppDataPath, _data.Value.AppSecret, _data.Value.OverrideLatestVersionId, _requestTimeoutCalculator)).WaitOne(); PatcherStatistics.TryDispatchSendEvent(PatcherStatistics.Event.PatcherStarted); while (true) { cancellationToken.ThrowIfCancellationRequested(); ThreadWaitForUserDecision(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); ThreadExecuteUserDecision(cancellationToken); } } catch (OperationCanceledException) { DebugLogger.Log("Patcher thread finished: thread has been cancelled."); } catch (ThreadInterruptedException) { DebugLogger.Log("Patcher thread finished: thread has been interrupted."); } catch (ThreadAbortException) { DebugLogger.Log("Patcher thread finished: thread has been aborted."); } catch (MultipleInstancesException exception) { DebugLogger.LogException(exception); Quit(); } catch (Exception exception) { DebugLogger.LogError("Patcher thread failed: an exception has occured."); DebugLogger.LogException(exception); } finally { _state.Value = PatcherState.None; } }
private void ThreadWaitForUserDecision(CancellationToken cancellationToken) { try { DebugLogger.Log("Waiting for user decision..."); _state.Value = PatcherState.WaitingForUserDecision; bool isInstalled = _app.IsInstalled(); DebugLogger.LogVariable(isInstalled, "isInstalled"); _canRepairApp.Value = false; // not implemented _canInstallApp.Value = !isInstalled; _canCheckForAppUpdates.Value = isInstalled; _canStartApp.Value = isInstalled; if (_canInstallApp.Value && _configuration.AutomaticallyInstallApp && !_hasAutomaticallyInstalledApp) { DebugLogger.Log("Automatically deciding to install app."); _hasAutomaticallyInstalledApp = true; _userDecision = UserDecision.InstallAppAutomatically; return; } if (_canCheckForAppUpdates.Value && _configuration.AutomaticallyCheckForAppUpdates && !_hasAutomaticallyCheckedForAppUpdate) { DebugLogger.Log("Automatically deciding to check for app updates."); _hasAutomaticallyCheckedForAppUpdate = true; _userDecision = UserDecision.CheckForAppUpdatesAutomatically; return; } if (_canStartApp.Value && _configuration.AutomaticallyStartApp && !_hasAutomaticallyStartedApp) { DebugLogger.Log("Automatically deciding to start app."); _hasAutomaticallyStartedApp = true; _userDecision = UserDecision.StartAppAutomatically; return; } _userDecisionSetEvent.Reset(); using (cancellationToken.Register(() => _userDecisionSetEvent.Set())) { cancellationToken.ThrowIfCancellationRequested(); _userDecisionSetEvent.WaitOne(); } cancellationToken.ThrowIfCancellationRequested(); DebugLogger.Log(string.Format("Waiting for user decision result: {0}.", _userDecision)); } catch (OperationCanceledException) { DebugLogger.Log("Waiting for user decision cancelled."); } catch (ThreadInterruptedException) { DebugLogger.Log("Waiting for user decision interrupted: thread has been interrupted. Rethrowing exception."); throw; } catch (ThreadAbortException) { DebugLogger.Log("Waiting for user decision aborted: thread has been aborted. Rethrowing exception."); throw; } catch (Exception) { DebugLogger.LogWarning("Error while waiting for user decision: an exception has occured. Rethrowing exception."); throw; } }