/// <summary> /// Completes this task. The delegate MUST call this method to complete the task. /// </summary> /// <param name="exception">The exception for the task.</param> /// <param name="actionResult">The task result for the task. Can include the exception.</param> /// <remarks>The signature includes exception since Complete(null) cannot be disambiguated otherwise. /// If the exception given is not null, then it will be stored in the task result as well. /// </remarks> public void Complete(Exception exception, AsyncTaskResult actionResult) { lock (m_syncRoot) { if (m_isCompleted) { if (s_isLoggingOn && this.Logger != null) { this.Logger.Log(Logger.LogLevel.Warning, String.Format("Task is completing more than once. Task = {0}", this.Name)); } return; } m_isCompleted = true; } EventHandler <AsyncTaskCompletedEventArgs> taskCompletedEventHandler = this.TaskCompleted; m_actionResult = actionResult; if (m_actionResult == null) { m_actionResult = new AsyncTaskResult(exception); } if (exception != null) { m_actionResult.Exception = exception; } if (taskCompletedEventHandler != null) { AsyncTaskCompletedEventArgs taskCompletedEventArgs = new AsyncTaskCompletedEventArgs(m_actionResult); taskCompletedEventHandler(this, taskCompletedEventArgs); } if (s_isLoggingOn && this.Logger != null) { this.Logger.Log(Logger.LogLevel.Info, "Completing <" + this.Name + ">"); } }
protected void StartupJoinConference(AsyncTask task, object state) { task.DoOneStep( delegate() { Conference conference = null; AsyncTaskResult conferenceActionResult = task.PreviousActionResult; // Normally, the previous task should be the one that scheduled the conference. But, play safe to allow other actions in between. while (conferenceActionResult != null) { ConferenceActionResult conferenceResult = conferenceActionResult as ConferenceActionResult; if (conferenceResult != null) { conference = conferenceResult.Conference; break; } conferenceActionResult = conferenceActionResult.PreviousActionResult; } if (conference == null) { task.Complete(new InvalidOperationException("StartupConferenceJoin: Conference must be scheduled before conference join operation.")); return; } ConferenceJoinOptions options = new ConferenceJoinOptions(); options.JoinMode = JoinMode.TrustedParticipant; m_tcuConversation.ConferenceSession.BeginJoin( conference.ConferenceUri, options, delegate(IAsyncResult ar) { task.DoFinalStep( delegate() { m_tcuConversation.ConferenceSession.EndJoin(ar); this.Logger.Log(Logger.LogLevel.Verbose, String.Format("ServiceHub {0} joined TCU conference {1}.", this.CustomerSession.Customer.UserUri, m_tcuConversation.ConferenceSession.ConferenceUri)); }); }, null); }); }
/// <summary> /// Do a step in the task. The parameter isFinal controls the completion of the task. /// </summary> /// <param name="step">The step to perform.</param> /// <remarks>If the step results in exception, the task is completed with that exception.</remarks> protected void DoStepCore(AsyncTaskStep step, bool isFinal) { Exception exception = null; AsyncTaskResult result = null; try { step(); result = this.TaskResult; // If task stored it, use it. if (isFinal) { this.Complete(null, result); } } catch (ArgumentException argexp) { exception = argexp; } catch (InvalidOperationException ioe) { exception = ioe; } catch (RealTimeException rte) { exception = rte; } catch (VoiceCompanionException vce) { exception = vce; } finally { if (result == null) { result = new AsyncTaskResult(exception); } if (exception != null) { result.Exception = exception; this.Complete(exception, result); } } }
/// <summary> /// Process Sequence serially. /// </summary> protected virtual void Process(object state) { AsyncTaskResult previousActionResult = state as AsyncTaskResult; // Can be null. AsyncTask task = null; lock (m_actions) { m_pendingAction = null; if (m_actions.Count > 0) { task = m_actions.Dequeue(); m_pendingAction = task; } } if (task == null) { // No more items in queue. Complete the starup operaton if needed. this.CompleteSequence(null); } else { Exception exception = null; try { task.TaskCompleted += delegate(object sender, AsyncTaskCompletedEventArgs e) { AsyncTask reportingAction = sender as AsyncTask; if (!Object.ReferenceEquals(reportingAction, task)) { this.Logger.Log(Logger.LogLevel.Warning, String.Format("Reporting task does not match pending task. Task is probably completing twice. Task = {0}", reportingAction.Name)); return; // Ignore this reporting. } if (task.Exception != null && this.Component.Logger != null) { this.Component.Logger.Log(Logger.LogLevel.Verbose, String.Format("<{0}> completed with exception.", task.Name), task.Exception); } else { this.Component.Logger.Log(Logger.LogLevel.Verbose, String.Format("**{0}({1})** <{2}> Completed Task.", this.Name, this.Component.Name, task.Name)); } bool completionNeeded = false; Exception ex = task.Exception; if (task.Exception != null && !task.IsOptional) { completionNeeded = true; } if (completionNeeded) { this.CompleteSequence(ex); } else { // Make sure the task chained previous result, if any. if (previousActionResult != null) { AsyncTaskResult currActionResult = e.ActionResult; if (currActionResult == null) // This should not be null if Task always returned it. Play safe. { currActionResult = new AsyncTaskResult(task.Exception); } // If the task completing has task result, then we need to chain. If not create a new one. currActionResult.PreviousActionResult = previousActionResult; } // Continue processing. System.Threading.ThreadPool.QueueUserWorkItem(this.Process, e.ActionResult); } }; this.Component.Logger.Log(Logger.LogLevel.Verbose, String.Format("**{0}({1})** <{2}> Started Task.", this.Name, this.Component.Name, task.Name)); task.PreviousActionResult = previousActionResult; task.StartTask(); } catch (RealTimeException rte) { exception = rte; } catch (InvalidOperationException ivo) { exception = ivo; } finally { if (exception != null && !task.IsOptional) { this.Component.Logger.Log(Logger.LogLevel.Verbose, String.Format("**{0}({1})** Completing due to exception while starting <{2}>.", this.Name, this.Component.Name, task.Name), exception); this.CompleteSequence(exception); } else if (exception != null) { this.Component.Logger.Log(Logger.LogLevel.Verbose, String.Format("**{0}({1})** resuming after exception while starting <{2}>.", this.Name, this.Component.Name, task.Name), exception); // Continue processing. Ignore failuer in task. System.Threading.ThreadPool.QueueUserWorkItem(this.Process); } // else, wait for the task to complete. } } }
public AsyncTaskCompletedEventArgs(AsyncTaskResult actionResult) { m_actionResult = actionResult; }
public AsyncTaskResult(Exception exception, AsyncTaskResult previousActionResult) { m_exception = exception; m_previousActionResult = previousActionResult; }