// Token: 0x06004044 RID: 16452 RVA: 0x000EF724 File Offset: 0x000ED924 private bool TrySetFromTask(Task task, bool lookForOce) { if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, base.Id, CausalityRelation.Join); } bool result = false; switch (task.Status) { case TaskStatus.RanToCompletion: { Task <TResult> task2 = task as Task <TResult>; if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, base.Id, AsyncCausalityStatus.Completed); } if (Task.s_asyncDebuggingEnabled) { Task.RemoveFromActiveTasks(base.Id); } result = base.TrySetResult((task2 != null) ? task2.Result : default(TResult)); break; } case TaskStatus.Canceled: result = base.TrySetCanceled(task.CancellationToken, task.GetCancellationExceptionDispatchInfo()); break; case TaskStatus.Faulted: { ReadOnlyCollection <ExceptionDispatchInfo> exceptionDispatchInfos = task.GetExceptionDispatchInfos(); ExceptionDispatchInfo exceptionDispatchInfo; OperationCanceledException ex; if (lookForOce && exceptionDispatchInfos.Count > 0 && (exceptionDispatchInfo = exceptionDispatchInfos[0]) != null && (ex = (exceptionDispatchInfo.SourceException as OperationCanceledException)) != null) { result = base.TrySetCanceled(ex.CancellationToken, exceptionDispatchInfo); } else { result = base.TrySetException(exceptionDispatchInfos); } break; } } return(result); }
private bool TrySetFromTask(Task task, bool lookForOce) { if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join); } bool flag = false; switch (task.Status) { case TaskStatus.RanToCompletion: Task <TResult> task1 = task as Task <TResult>; if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed); } if (Task.s_asyncDebuggingEnabled) { Task.RemoveFromActiveTasks(this.Id); } flag = this.TrySetResult(task1 != null ? task1.Result : default(TResult)); break; case TaskStatus.Canceled: flag = this.TrySetCanceled(task.CancellationToken, (object)task.GetCancellationExceptionDispatchInfo()); break; case TaskStatus.Faulted: ReadOnlyCollection <ExceptionDispatchInfo> exceptionDispatchInfos = task.GetExceptionDispatchInfos(); ExceptionDispatchInfo exceptionDispatchInfo; OperationCanceledException canceledException; flag = !lookForOce || exceptionDispatchInfos.Count <= 0 || ((exceptionDispatchInfo = exceptionDispatchInfos[0]) == null || (canceledException = exceptionDispatchInfo.SourceException as OperationCanceledException) == null) ? this.TrySetException((object)exceptionDispatchInfos) : this.TrySetCanceled(canceledException.CancellationToken, (object)exceptionDispatchInfo); break; } return(flag); }
/// <summary>Completes the task from the completed asynchronous operation.</summary> /// <param name="asyncInfo">The asynchronous operation.</param> /// <param name="getResultsFunction">A function used to retrieve the TResult from the async operation; may be null.</param> /// <param name="asyncStatus">The status of the asynchronous operation.</param> private void Complete(IAsyncInfo asyncInfo, Func <IAsyncInfo, TResult> getResultsFunction, AsyncStatus asyncStatus) { if (asyncInfo == null) { throw new ArgumentNullException(nameof(asyncInfo)); } Contract.EndContractBlock(); if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled) { System.Threading.Tasks.Task.RemoveFromActiveTasks(base.Task.Id); } try { Debug.Assert(asyncInfo.Status == asyncStatus, "asyncInfo.Status does not match asyncStatus; are we dealing with a faulty IAsyncInfo implementation?"); // Assuming a correct underlying implementation, the task should not have been // completed yet. If it is completed, we shouldn't try to do any further work // with the operation or the task, as something is horked. bool taskAlreadyCompleted = Task.IsCompleted; Debug.Assert(!taskAlreadyCompleted, "Expected the task to not yet be completed."); if (taskAlreadyCompleted) { throw new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } // Clean up our registration with the cancellation token, noting that we're now in the process of cleaning up. CancellationTokenRegistration ctr; lock (StateLock) { _completing = true; ctr = _ctr; // under lock to avoid torn reads _ctr = default(CancellationTokenRegistration); } ctr.Unregister(); // It's ok if we end up unregistering a not-initialized registration; it'll just be a nop. try { // Find out how the async operation completed. It must be in a terminal state. bool terminalState = asyncStatus == AsyncStatus.Completed || asyncStatus == AsyncStatus.Canceled || asyncStatus == AsyncStatus.Error; Debug.Assert(terminalState, "The async operation should be in a terminal state."); if (!terminalState) { throw new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } // Retrieve the completion data from the IAsyncInfo. TResult result = default(TResult); Exception error = null; if (asyncStatus == AsyncStatus.Error) { error = asyncInfo.ErrorCode; // Defend against a faulty IAsyncInfo implementation: if (error == null) { Debug.Assert(false, "IAsyncInfo.Status == Error, but ErrorCode returns a null Exception (implying S_OK)."); error = new InvalidOperationException(SR.InvalidOperation_InvalidAsyncCompletion); } else { error = RestrictedErrorInfoHelper.AttachRestrictedErrorInfo(asyncInfo.ErrorCode); } } else if (asyncStatus == AsyncStatus.Completed && getResultsFunction != null) { try { result = getResultsFunction(asyncInfo); } catch (Exception resultsEx) { // According to the WinRT team, this can happen in some egde cases, such as marshalling errors in GetResults. error = resultsEx; asyncStatus = AsyncStatus.Error; } } // Nothing to retrieve for a canceled operation or for a completed operation with no result. // Complete the task based on the previously retrieved results: bool success = false; switch (asyncStatus) { case AsyncStatus.Completed: if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, base.Task.Id, AsyncCausalityStatus.Completed); } success = base.TrySetResult(result); break; case AsyncStatus.Error: Debug.Assert(error != null, "The error should have been retrieved previously."); success = base.TrySetException(error); break; case AsyncStatus.Canceled: success = base.TrySetCanceled(_ct.IsCancellationRequested ? _ct : new CancellationToken(true)); break; } Debug.Assert(success, "Expected the outcome to be successfully transfered to the task."); } catch (Exception exc) { // This really shouldn't happen, but could in a variety of misuse cases // such as a faulty underlying IAsyncInfo implementation. Debug.Assert(false, string.Format("Unexpected exception in Complete: {0}", exc.ToString())); if (AsyncCausalityTracer.LoggingOn) { AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, base.Task.Id, AsyncCausalityStatus.Error); } // For these cases, store the exception into the task so that it makes its way // back to the caller. Only if something went horribly wrong and we can't store the exception // do we allow it to be propagated out to the invoker of the Completed handler. if (!base.TrySetException(exc)) { Debug.Assert(false, "The task was already completed and thus the exception couldn't be stored."); throw; } } } finally { // We may be called on an STA thread which we don't own, so make sure that the RCW is released right // away. Otherwise, if we leave it up to the finalizer, the apartment may already be gone. if (Marshal.IsComObject(asyncInfo)) { Marshal.ReleaseComObject(asyncInfo); } } } // private void Complete(..)