コード例 #1
0
        private static Task <TOuterResult> ThenImpl <TTask, TOuterResult>(this TTask task, Func <TTask, Task <TOuterResult> > continuation, CancellationToken cancellationToken, bool runSynchronously)
            where TTask : Task
        {
            // Stay on the same thread if we can
            if (task.IsCompleted)
            {
                if (task.IsFaulted)
                {
                    return(TaskHelpers.FromErrors <TOuterResult>(task.Exception.InnerExceptions));
                }
                if (task.IsCanceled || cancellationToken.IsCancellationRequested)
                {
                    return(TaskHelpers.Canceled <TOuterResult>());
                }
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    try
                    {
                        return(continuation(task));
                    }
                    catch (Exception ex)
                    {
                        return(TaskHelpers.FromError <TOuterResult>(ex));
                    }
                }
            }

            // Split into a continuation method so that we don't create a closure unnecessarily
            return(ThenImplContinuation(task, continuation, cancellationToken, runSynchronously));
        }
コード例 #2
0
        private static IEnumerable <Task <object> > CanceledTaskEnumerable_Generic(List <string> log)
        {
            log.Add("first");
            yield return(TaskHelpers.Canceled <object>());

            log.Add("second");
        }
コード例 #3
0
        /// <summary>
        /// Changes the return value of a task to the given result, if the task ends in the RanToCompletion state.
        /// This potentially imposes an extra ContinueWith to convert a non-completed task, so use this with caution.
        /// </summary>
        internal static Task <TResult> ToTask <TResult>(this Task task, CancellationToken cancellationToken = default(CancellationToken), TResult result = default(TResult))
        {
            if (task == null)
            {
                return(null);
            }

            // Stay on the same thread if we can
            if (task.IsCompleted)
            {
                if (task.IsFaulted)
                {
                    return(TaskHelpers.FromErrors <TResult>(task.Exception.InnerExceptions));
                }
                if (task.IsCanceled || cancellationToken.IsCancellationRequested)
                {
                    return(TaskHelpers.Canceled <TResult>());
                }
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    return(TaskHelpers.FromResult(result));
                }
            }

            // Split into a continuation method so that we don't create a closure unnecessarily
            return(ToTaskContinuation(task, result));
        }
コード例 #4
0
        public void Canceled_Generic_ReturnsCanceledTask()
        {
            Task <string> result = TaskHelpers.Canceled <string>();

            Assert.NotNull(result);
            Assert.True(result.IsCanceled);
        }
コード例 #5
0
        private static IEnumerable <Task> CanceledTaskEnumerable(List <string> log)
        {
            log.Add("first");
            yield return(TaskHelpers.Canceled());

            log.Add("second");
        }
コード例 #6
0
        public void Canceled_ReturnsCanceledTask()
        {
            Task result = TaskHelpers.Canceled();

            Assert.NotNull(result);
            Assert.True(result.IsCanceled);
        }
コード例 #7
0
        public static Task IterateImpl(IEnumerator <Task> enumerator, CancellationToken cancellationToken)
        {
            try
            {
                while (true)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(TaskHelpers.Canceled());
                    }

                    if (!enumerator.MoveNext())
                    {
                        return(TaskHelpers.Completed());
                    }

                    var currentTask = enumerator.Current;
                    if (currentTask.Status == TaskStatus.RanToCompletion)
                    {
                        continue;
                    }

                    if (currentTask.IsCanceled || currentTask.IsFaulted)
                    {
                        return(currentTask);
                    }

                    return(IterateImplIncompleteTask(enumerator, currentTask, cancellationToken));
                }
            }
            catch (Exception ex)
            {
                return(TaskHelpers.FromError(ex));
            }
        }
コード例 #8
0
        public void TrySetFromTask_IfSourceTaskIsCanceled_CancelsTaskCompletionSource()
        {
            TaskCompletionSource <string> tcs = new TaskCompletionSource <string>();
            Task canceledTask = TaskHelpers.Canceled <object>();

            tcs.TrySetFromTask(canceledTask);

            Assert.Equal(TaskStatus.Canceled, tcs.Task.Status);
        }
コード例 #9
0
        public async Task ConvertFromCancelledTaskShouldBeHandled()
        {
            // Arrange
            var task = TaskHelpers.Canceled().CastToObject();

            // Act & Assert
            await Assert.ThrowsAsync <TaskCanceledException>(() => task);

            Assert.Equal(TaskStatus.Canceled, task.Status);
        }
コード例 #10
0
        internal static Task <TOuterResult> CastFromobject <TOuterResult>(this Task <object> task)
        {
            // Stay on the same thread if we can
            if (task.IsCompleted)
            {
                if (task.IsFaulted)
                {
                    return(TaskHelpers.FromErrors <TOuterResult>(task.Exception.InnerExceptions));
                }
                if (task.IsCanceled)
                {
                    return(TaskHelpers.Canceled <TOuterResult>());
                }
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    try
                    {
                        return(TaskHelpers.FromResult <TOuterResult>((TOuterResult)task.Result));
                    }
                    catch (Exception exception)
                    {
                        return(TaskHelpers.FromError <TOuterResult>(exception));
                    }
                }
            }

            TaskCompletionSource <TOuterResult> tcs = new TaskCompletionSource <TOuterResult>();

            // schedule a synchronous task to cast: no need to worry about sync context or try/catch
            task.ContinueWith(innerTask =>
            {
                if (innerTask.IsFaulted)
                {
                    tcs.SetException(innerTask.Exception.InnerExceptions);
                }
                else if (innerTask.IsCanceled)
                {
                    tcs.SetCanceled();
                }
                else
                {
                    try
                    {
                        tcs.SetResult((TOuterResult)innerTask.Result);
                    }
                    catch (Exception exception)
                    {
                        tcs.SetException(exception);
                    }
                }
            }, TaskContinuationOptions.ExecuteSynchronously);

            return(tcs.Task);
        }
コード例 #11
0
        public void TryGetResult_CanceledTask_ReturnsFalse()
        {
            // Arrange
            var task = TaskHelpers.Canceled <int>();

            // Act
            int  value;
            bool result = task.TryGetResult(out value);

            // Assert
            Assert.False(result);
        }
コード例 #12
0
        public static Task <TOuterResult> CastFromObject <TOuterResult>(this Task <object> task)
        {
            if (task.IsCompleted)
            {
                if (task.IsFaulted)
                {
                    return(TaskHelpers.FromErrors <TOuterResult>(task.Exception.InnerExceptions));
                }
                if (task.IsCanceled)
                {
                    return(TaskHelpers.Canceled <TOuterResult>());
                }
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    try
                    {
                        return(TaskHelpers.FromResult((TOuterResult)task.Result));
                    }
                    catch (Exception exception)
                    {
                        return(TaskHelpers.FromError <TOuterResult>(exception));
                    }
                }
            }

            var tcs = new TaskCompletionSource <TOuterResult>();

            task.ContinueWith(innerTask =>
            {
                if (innerTask.IsFaulted)
                {
                    tcs.SetException(innerTask.Exception.InnerExceptions);
                }
                else if (innerTask.IsCanceled)
                {
                    tcs.SetCanceled();
                }
                else
                {
                    try
                    {
                        tcs.SetResult((TOuterResult)innerTask.Result);
                    }
                    catch (Exception exception)
                    {
                        tcs.SetException(exception);
                    }
                }
            }, TaskContinuationOptions.ExecuteSynchronously);

            return(tcs.Task);
        }
コード例 #13
0
 public CatchResult Throw()
 {
     if (base.Task.IsFaulted || base.Task.IsCanceled)
     {
         return(new CatchResult {
             Task = base.Task
         });
     }
     // Canceled via CancelationToken
     return(new CatchResult {
         Task = TaskHelpers.Canceled()
     });
 }
コード例 #14
0
        public Task ConvertFromCancelledTaskOfStringShouldBeHandled()
        {
            // Arrange
            return(TaskHelpers.Canceled <string>()

                   // Act
                   .CastToObject()

                   // Assert
                   .ContinueWith((task) =>
            {
                Assert.Equal(TaskStatus.Canceled, task.Status);
            }));
        }
コード例 #15
0
        private static Task IterateImpl(IEnumerator <Task> enumerator, CancellationToken cancellationToken, Func <Task, bool> breakCondition)
        {
            try
            {
                while (true)
                {
                    // short-circuit: iteration canceled
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(TaskHelpers.Canceled());
                    }

                    // short-circuit: iteration complete
                    if (!enumerator.MoveNext())
                    {
                        return(TaskHelpers.Completed());
                    }

                    // fast case: Task completed synchronously & successfully
                    Task currentTask = enumerator.Current;
                    if (currentTask.Status == TaskStatus.RanToCompletion)
                    {
                        if (breakCondition != null && breakCondition(currentTask))
                        {
                            return(currentTask);
                        }

                        continue;
                    }

                    // fast case: Task completed synchronously & unsuccessfully
                    if (currentTask.IsCanceled || currentTask.IsFaulted)
                    {
                        return(currentTask);
                    }

                    // slow case: Task isn't yet complete
                    return(IterateImplIncompleteTask(enumerator, currentTask, cancellationToken, breakCondition));
                }
            }
            catch (Exception ex)
            {
                return(TaskHelpers.FromError(ex));
            }
        }
コード例 #16
0
        private static Task <TResult> CatchImpl <TResult>(this Task task, Func <Task <TResult> > continuation, CancellationToken cancellationToken)
        {
            // Stay on the same thread if we can
            if (task.IsCompleted)
            {
                if (task.IsFaulted)
                {
                    try
                    {
                        Task <TResult> resultTask = continuation();
                        if (resultTask == null)
                        {
                            // Not a resource because this is an internal class, and this is a guard clause that's intended
                            // to be thrown by us to us, never escaping out to end users.
                            throw new InvalidOperationException("You must set the Task property of the CatchInfo returned from the TaskHelpersExtensions.Catch continuation.");
                        }

                        return(resultTask);
                    }
                    catch (Exception ex)
                    {
                        return(TaskHelpers.FromError <TResult>(ex));
                    }
                }
                if (task.IsCanceled || cancellationToken.IsCancellationRequested)
                {
                    return(TaskHelpers.Canceled <TResult>());
                }

                if (task.Status == TaskStatus.RanToCompletion)
                {
                    TaskCompletionSource <TResult> tcs = new TaskCompletionSource <TResult>();
                    tcs.TrySetFromTask(task);
                    return(tcs.Task);
                }
            }

            // Split into a continuation method so that we don't create a closure unnecessarily
            return(CatchImplContinuation(task, continuation));
        }
コード例 #17
0
        private static Task <TOuterResult> ThenImplContinuation <TOuterResult, TTask>(TTask task, Func <TTask, Task <TOuterResult> > continuation, CancellationToken cancellationToken)
            where TTask : Task
        {
            SynchronizationContext syncContext = SynchronizationContext.Current;

            return(task.ContinueWith(innerTask =>
            {
                if (innerTask.IsFaulted)
                {
                    return TaskHelpers.FromErrors <TOuterResult>(innerTask.Exception.InnerExceptions);
                }
                if (innerTask.IsCanceled || cancellationToken.IsCancellationRequested)
                {
                    return TaskHelpers.Canceled <TOuterResult>();
                }

                TaskCompletionSource <Task <TOuterResult> > tcs = new TaskCompletionSource <Task <TOuterResult> >();
                if (syncContext != null)
                {
                    syncContext.Post(state =>
                    {
                        try
                        {
                            tcs.TrySetResult(continuation(task));
                        }
                        catch (Exception ex)
                        {
                            tcs.TrySetException(ex);
                        }
                    }, state: null);
                }
                else
                {
                    tcs.TrySetResult(continuation(task));
                }
                return tcs.Task.FastUnwrap();
            }).FastUnwrap());
        }
コード例 #18
0
        public static Task <object> CastToObject(this Task task)
        {
            if (task.IsCompleted)
            {
                if (task.IsFaulted)
                {
                    return(TaskHelpers.FromErrors <object>(task.Exception.InnerExceptions));
                }
                if (task.IsCanceled)
                {
                    return(TaskHelpers.Canceled <object>());
                }
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    return(TaskHelpers.FromResult((object)null));
                }
            }

            var tcs = new TaskCompletionSource <object>();

            task.ContinueWith(innerTask =>
            {
                if (innerTask.IsFaulted)
                {
                    tcs.SetException(innerTask.Exception.InnerExceptions);
                }
                else if (innerTask.IsCanceled)
                {
                    tcs.SetCanceled();
                }
                else
                {
                    tcs.SetResult(null);
                }
            }, TaskContinuationOptions.ExecuteSynchronously);

            return(tcs.Task);
        }