// 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);
        }
示例#2
0
        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);
        }
示例#3
0
        /// <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(..)