/// <summary> /// Initializes a new instance of the <see cref="PackageExecutionStateChangedEventArgs"/> class. /// </summary> /// <param name="package">The package that fired the event.</param> /// <param name="oldState">The old execution state of the package.</param> /// <param name="newState">The new execution state of the package.</param> /// <param name="exception">The exception that occured during discovery of the state change.</param> public PackageExecutionStateChangedEventArgs(XboxPackage package, PackageExecutionState oldState, PackageExecutionState newState, Exception exception) { this.Package = package; this.OldState = oldState; this.NewState = newState; this.Exception = exception; }
public void TestExecutionStateEventFiresOnNewState() { PackageExecutionState state = PackageExecutionState.Constrained; int numberOfTimesStateChanged = 0; ShimXboxConsoleAdapterBase.AllInstances.QueryPackageExecutionStateStringXboxPackageDefinition = (adapter, systemIpAddress, package) => { switch (state) { case PackageExecutionState.Constrained: ++numberOfTimesStateChanged; state = PackageExecutionState.Running; break; case PackageExecutionState.Running: ++numberOfTimesStateChanged; state = PackageExecutionState.Suspended; break; case PackageExecutionState.Suspended: ++numberOfTimesStateChanged; state = PackageExecutionState.Suspending; break; case PackageExecutionState.Suspending: ++numberOfTimesStateChanged; state = PackageExecutionState.Terminated; break; case PackageExecutionState.Terminated: ++numberOfTimesStateChanged; state = PackageExecutionState.Unknown; break; case PackageExecutionState.Unknown: default: break; } return(state); }; int numberOfTimesHandlerEntered = 0; EventHandler <PackageExecutionStateChangedEventArgs> handler = (o, e) => { ++numberOfTimesHandlerEntered; }; this.xboxPackage.ExecutionStateChanged += handler; Thread.Sleep(this.timeToWaitForPolling); Assert.AreEqual(numberOfTimesStateChanged, numberOfTimesHandlerEntered, "The handler was not called for each time that the state changed."); }
public void TestExecutionStateEventMultipleHandlers() { PackageExecutionState state = PackageExecutionState.Constrained; ShimXboxConsoleAdapterBase.AllInstances.QueryPackageExecutionStateStringXboxPackageDefinition = (adapter, systemIpAddress, package) => { if (state == PackageExecutionState.Constrained) { state = PackageExecutionState.Running; } else { state = PackageExecutionState.Constrained; } return(state); }; bool handler1Entered = false; bool handler2Entered = false; EventHandler <PackageExecutionStateChangedEventArgs> handler1 = (o, e) => { handler1Entered = true; }; EventHandler <PackageExecutionStateChangedEventArgs> handler2 = (o, e) => { handler2Entered = true; }; this.xboxPackage.ExecutionStateChanged += handler1; this.xboxPackage.ExecutionStateChanged += handler2; Thread.Sleep(this.timeToWaitForPolling); // Ensuring multiple handlers are called. Assert.IsTrue(handler1Entered, "The handler was not called after subscribing."); Assert.IsTrue(handler2Entered, "The handler was not called after subscribing."); this.xboxPackage.ExecutionStateChanged -= handler2; handler1Entered = false; handler2Entered = false; Thread.Sleep(this.timeToWaitForPolling); // Ensuring that after a handler unsubscribes, the other handlers still get called, // and after unsubscribing, that handler doesn't get called. Assert.IsTrue(handler1Entered, "The handler was not called after another handler unsubscribed."); Assert.IsFalse(handler2Entered, "The handler was called after subscribing."); }
public void TestExecutionStateEventExceptionNotification() { XboxException queryException = new XboxException(); bool firstQueryFinished = false; bool pollingContinued = false; ShimXboxConsoleAdapterBase.AllInstances.QueryPackageExecutionStateStringXboxPackageDefinition = (adapter, systemIpAddress, package) => { if (!firstQueryFinished) { firstQueryFinished = true; throw queryException; } else { pollingContinued = true; } return(PackageExecutionState.Constrained); }; bool handlerWasCalled = false; PackageExecutionState newState = PackageExecutionState.Terminated; Exception eventException = null; EventHandler <PackageExecutionStateChangedEventArgs> handler = (o, e) => { handlerWasCalled = true; newState = e.NewState; eventException = e.Exception; }; this.xboxPackage.ExecutionStateChanged += handler; Thread.Sleep(this.timeToWaitForPolling); Assert.IsFalse(pollingContinued, "The polling continued after the exception."); Assert.IsTrue(handlerWasCalled, "The handler was not called after the exception."); Assert.AreEqual(PackageExecutionState.Unknown, newState, "The EventArgs didn't have the expected new package state."); Assert.IsNotNull(eventException, "The EventArgs didn't have the expected exception"); Assert.AreSame(queryException, eventException, "The EventArgs didn't have the expected exception"); }
private void ExecutionStatePollingAction(CancellationToken token) { // This task uses cancellation to end the polling when nobody's // listening. Therefore, this method just returns when a cancellation // is requested instead of throwing the cancellation exception. // Not checking the package for the initial state since it would be a // rather complex implementation to handle the case where the initial check // throws an exception and then gracefully allow certain types of exceptions // before finally starting the actual polling. It should be okay to // have a event fired if the initial state is something other than // unknown. PackageExecutionState oldState = PackageExecutionState.Unknown; try { while (!token.IsCancellationRequested) { Task.Delay(this.executionStatePollingTime).Wait(); if (token.IsCancellationRequested) { return; } try { var newState = this.ExecutionState; if (oldState != newState) { if (this.executionStateChanged != null && !token.IsCancellationRequested) { this.executionStateChanged.Invoke(this, new PackageExecutionStateChangedEventArgs(this, oldState, newState)); } oldState = newState; } } catch (CannotConnectException ex) { // Unable to talk to the console right now. // Will continue to poll in case communication is restored. System.Diagnostics.Debug.WriteLine(ex); } catch (UnauthorizedAccessException ex) { System.Diagnostics.Debug.WriteLine(ex); } catch (XboxConsoleException ex) { var innerException = ex.InnerException as COMException; if (innerException != null) { switch (innerException.ErrorCode) { case unchecked ((int)0x8007045B): case unchecked ((int)0x8C11040E): { // This error codes mean that system is in the process of shutting down. // Will continue to poll in case the console is started up again. System.Diagnostics.Debug.WriteLine(ex); } break; } } else { throw; } } } } catch (XboxException ex) { // Something we can't handle has happened. The polling will be stopped // since we can't know what will happen if we continue to poll. System.Diagnostics.Debug.WriteLine(ex); if (this.executionStateChanged != null && !token.IsCancellationRequested) { this.executionStateChanged.Invoke(this, new PackageExecutionStateChangedEventArgs(this, oldState, PackageExecutionState.Unknown, ex)); } } }
/// <summary> /// Initializes a new instance of the <see cref="PackageExecutionStateChangedEventArgs"/> class. /// </summary> /// <param name="package">The package that fired the event.</param> /// <param name="oldState">The old execution state of the package.</param> /// <param name="newState">The new execution state of the package.</param> public PackageExecutionStateChangedEventArgs(XboxPackage package, PackageExecutionState oldState, PackageExecutionState newState) : this(package, oldState, newState, null) { // Nothing needed here. }