Esempio n. 1
0
        public static Task AsTask <TProgress>(this IAsyncActionWithProgress <TProgress> source, CancellationToken cancellationToken, IProgress <TProgress> progress)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            // TODO: Handle the scenario where the 'IAsyncActionWithProgress' is actually a task (i.e. originated from native code
            // but projected into an IAsyncActionWithProgress)

            switch (source.Status)
            {
            case AsyncStatus.Completed:
                return(Task.CompletedTask);

            case AsyncStatus.Error:
                return(Task.FromException(source.ErrorCode));

            case AsyncStatus.Canceled:
                return(Task.FromCanceled(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true)));
            }

            if (progress != null)
            {
                SetProgress(source, progress);
            }

            var bridge = new AsyncInfoToTaskBridge <VoidValueTypeParameter, TProgress>(cancellationToken);

            source.Completed = new AsyncActionWithProgressCompletedHandler <TProgress>(bridge.CompleteFromAsyncActionWithProgress);
            bridge.RegisterForCancellation(source);
            return(bridge.Task);
        }
Esempio n. 2
0
        public static Task <TResult> AsTask <TResult>(this IAsyncOperation <TResult> source, CancellationToken cancellationToken)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            // TODO: Handle the scenario where the 'IAsyncOperation' is actually a task (i.e. originated from native code
            // but projected into an IAsyncOperation)

            switch (source.Status)
            {
            case AsyncStatus.Completed:
                return(Task.FromResult(source.GetResults()));

            case AsyncStatus.Error:
                return(Task.FromException <TResult>(source.ErrorCode));

            case AsyncStatus.Canceled:
                return(Task.FromCanceled <TResult>(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true)));
            }

            var bridge = new AsyncInfoToTaskBridge <TResult, VoidValueTypeParameter>(cancellationToken);

            source.Completed = new AsyncOperationCompletedHandler <TResult>(bridge.CompleteFromAsyncOperation);
            bridge.RegisterForCancellation(source);
            return(bridge.Task);
        }
Esempio n. 3
0
        /// <summary>Gets a Task to represent the asynchronous operation.</summary>
        /// <param name="source">The asynchronous operation.</param>
        /// <param name="cancellationToken">The token used to request cancellation of the asynchronous operation.</param>
        /// <returns>The Task representing the asynchronous operation.</returns>
        public static Task AsTask(this IAsyncAction source, CancellationToken cancellationToken)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            Contract.EndContractBlock();

            // If source is actually a NetFx-to-WinRT adapter, unwrap it instead of creating a new Task:
            var wrapper = source as TaskToAsyncActionAdapter;

            if (wrapper != null && !wrapper.CompletedSynchronously)
            {
                Task innerTask = wrapper.Task;
                Debug.Assert(innerTask != null);
                Debug.Assert(innerTask.Status != TaskStatus.Created);

                if (!innerTask.IsCompleted)
                {
                    // The race here is benign: If the task completes here, the concatination is useless, but not damaging.
                    if (cancellationToken.CanBeCanceled && wrapper.CancelTokenSource != null)
                    {
                        ConcatenateCancelTokens(cancellationToken, wrapper.CancelTokenSource, innerTask);
                    }
                }

                return(innerTask);
            }

            // Fast path to return a completed Task if the operation has already completed:
            switch (source.Status)
            {
            case AsyncStatus.Completed:
                return(Task.CompletedTask);

            case AsyncStatus.Error:
                return(Task.FromException(source.ErrorCode.AttachRestrictedErrorInfo()));

            case AsyncStatus.Canceled:
                return(Task.FromCanceled(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true)));
            }

            // Benign race: source may complete here. Things still work, just not taking the fast path.

            // Source is not a NetFx-to-WinRT adapter, but a native future. Hook up the task:
            var bridge = new AsyncInfoToTaskBridge <VoidValueTypeParameter>(cancellationToken);

            try
            {
                source.Completed = new AsyncActionCompletedHandler(bridge.CompleteFromAsyncAction);
                bridge.RegisterForCancellation(source);
            }
            catch
            {
                AsyncCausalitySupport.RemoveFromActiveTasks(bridge.Task);
            }
            return(bridge.Task);
        }
Esempio n. 4
0
        /// <summary>Gets a Task to represent the asynchronous operation.</summary>
        /// <param name="source">The asynchronous operation.</param>
        /// <param name="cancellationToken">The token used to request cancellation of the asynchronous operation.</param>
        /// <param name="progress">The progress object used to receive progress updates.</param>
        /// <returns>The Task representing the asynchronous operation.</returns>
        public static Task <TResult> AsTask <TResult, TProgress>(this IAsyncOperationWithProgress <TResult, TProgress> source,
                                                                 CancellationToken cancellationToken, IProgress <TProgress> progress)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            Contract.EndContractBlock();

            // If source is actually a NetFx-to-WinRT adapter, unwrap it instead of creating a new Task:
            var wrapper = source as TaskToAsyncOperationWithProgressAdapter <TResult, TProgress>;

            if (wrapper != null && !wrapper.CompletedSynchronously)
            {
                Task <TResult> innerTask = wrapper.Task as Task <TResult>;
                Debug.Assert(innerTask != null);
                Debug.Assert(innerTask.Status != TaskStatus.Created);  // Is WaitingForActivation a legal state at this moment?

                if (!innerTask.IsCompleted)
                {
                    // The race here is benign: If the task completes here, the concatinations are useless, but not damaging.

                    if (cancellationToken.CanBeCanceled && wrapper.CancelTokenSource != null)
                    {
                        ConcatenateCancelTokens(cancellationToken, wrapper.CancelTokenSource, innerTask);
                    }

                    if (progress != null)
                    {
                        ConcatenateProgress(source, progress);
                    }
                }

                return(innerTask);
            }

            // Fast path to return a completed Task if the operation has already completed
            switch (source.Status)
            {
            case AsyncStatus.Completed:
                return(Task.FromResult(source.GetResults()));

            case AsyncStatus.Error:
                return(Task.FromException <TResult>(RestrictedErrorInfoHelper.AttachRestrictedErrorInfo(source.ErrorCode)));

            case AsyncStatus.Canceled:
                return(Task.FromCancellation <TResult>(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true)));
            }

            // Benign race: source may complete here. Things still work, just not taking the fast path.

            // Forward progress reports:
            if (progress != null)
            {
                ConcatenateProgress(source, progress);
            }

            // Source is not a NetFx-to-WinRT adapter, but a native future. Hook up the task:
            var bridge = new AsyncInfoToTaskBridge <TResult, TProgress>(cancellationToken);

            source.Completed = new AsyncOperationWithProgressCompletedHandler <TResult, TProgress>(bridge.CompleteFromAsyncOperationWithProgress);
            bridge.RegisterForCancellation(source);

            return(bridge.Task);
        }