/// <summary> /// Loads the specified session. /// </summary> /// <param name="session">The session to load.</param> /// <returns> /// <see cref="System.Threading.Tasks.Task{T}" /> that can be awaited. /// </returns> /// <exception cref="ArgumentNullException"> /// If <paramref name="session" /> is null. /// </exception> /// <exception cref="ArgumentException"> /// If <paramref name="session" /> has been already loaded or canceled. /// </exception> public async Task<Session> Load( Session session ) { //Contract.Requires<ArgumentNullException>( session != null, "session" ); if( session.State != SessionState.Created ) { throw new ArgumentException( "Invalid session state.", "session" ); } ActionRegistration action; if( !_actions.TryGetValue( session.Action, out action ) ) { throw new Exception( "Session with invalid action." ); } if( !action.Validate( session ) ) { session.State = SessionState.Complete; return session; } lock( _sessions ) { if( session.Exclusive ) { if( _sessions.Count > 0 ) { foreach( var existingSession in _sessions ) { existingSession.Cancel(); } _sessions.Clear(); } } _sessions.Add( session ); } OnSessionStarted( new SessionEventArgs( session ) ); if( session.IsCancellationRequested ) { lock( _sessions ) { _sessions.Remove( session ); } return session; } session.State = SessionState.Active; if( DataExchangeService != null ) { DataExchangeService.BeginDataExchange(); } Task task = null; try { task = action.Process( session ); } catch( Exception ex ) { lock( _sessions ) { _sessions.Remove( session ); } if( DataExchangeService != null ) { DataExchangeService.EndDataExchange(); } var canceled = ex is OperationCanceledException; var eventArgs = new SessionAbortedEventArgs( session, canceled ? null : ex ); OnSessionAborted( eventArgs ); if( !canceled && !eventArgs.Handled ) { if( ViewModelExceptionHandlingService == null || !ViewModelExceptionHandlingService.HandleException( this, session, ex ) ) { throw; } } return session; } if( task == null ) { lock( _sessions ) { _sessions.Remove( session ); } session.State = SessionState.Complete; if( DataExchangeService != null ) { DataExchangeService.EndDataExchange(); } OnSessionComplete( new SessionEventArgs( session ) ); return session; } try { await task; session.State = SessionState.Complete; OnSessionComplete( new SessionEventArgs( session ) ); } catch( Exception ex ) { var canceled = ex is OperationCanceledException; var eventArgs = new SessionAbortedEventArgs( session, canceled ? null : ex ); var aggregateException = ex as AggregateException; if( aggregateException != null ) { canceled = aggregateException.InnerExceptions.OfType<OperationCanceledException>().Any(); } OnSessionAborted( eventArgs ); if( !canceled && !eventArgs.Handled ) { if( ViewModelExceptionHandlingService == null || !ViewModelExceptionHandlingService.HandleException( this, session, ex ) ) { throw; } } } finally { lock( _sessions ) { _sessions.Remove( session ); } if( DataExchangeService != null ) { DataExchangeService.EndDataExchange(); } } return session; }
/// <summary> /// Raises the session aborted event. /// </summary> /// <param name="e"> /// The <see cref="Digillect.Mvvm.SessionAbortedEventArgs" /> instance containing the event data. /// </param> protected virtual void OnSessionAborted( SessionAbortedEventArgs e ) { if( SessionAborted != null ) { SessionAborted( this, e ); } }