Esempio n. 1
0
        /// <summary>
        /// Creates a Task that will complete after a time delay.
        /// </summary>
        /// <param name="millisecondsDelay">The number of milliseconds to wait before completing the returned Task</param>
        /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned Task</param>
        /// <returns>A Task that represents the time delay</returns>
        /// <exception cref="T:System.ArgumentOutOfRangeException">
        /// The <paramref name="millisecondsDelay"/> is less than -1.
        /// </exception>
        /// <exception cref="T:System.ObjectDisposedException">
        /// The provided <paramref name="cancellationToken"/> has already been disposed.
        /// </exception>
        /// <remarks>
        /// If the cancellation token is signaled before the specified time delay, then the Task is completed in
        /// Canceled state.  Otherwise, the Task is completed in RanToCompletion state once the specified time
        /// delay has expired.
        /// </remarks>
        public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
        {
            // Throw on non-sensical time
            if (millisecondsDelay < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(millisecondsDelay), "The value needs to be either -1 (signifying an infinite timeout), 0 or a positive integer.");
            }
            Contract.EndContractBlock();
            // some short-cuts in case quick completion is in order
            if (cancellationToken.IsCancellationRequested)
            {
                // return a Task created as already-Canceled
                return(FromCancellation(cancellationToken));
            }
            if (millisecondsDelay == 0)
            {
                // return a Task created as already-RanToCompletion
                return(CompletedTask);
            }
            var source = new TaskCompletionSource <bool>();

            if (millisecondsDelay > 0)
            {
                var timeout = RootedTimeout.Launch
                              (
                    () =>
                {
                    try
                    {
                        source.SetResult(true);
                    }
                    catch (InvalidOperationException exception)
                    {
                        // Already cancelled
                        GC.KeepAlive(exception);
                    }
                },
                    millisecondsDelay,
                    cancellationToken
                              );
                source.Task.SetPromiseCheck(() => timeout.CheckRemaining());
            }
            if (cancellationToken.CanBeCanceled)
            {
                cancellationToken.Register
                (
                    () =>
                {
                    try
                    {
                        source.SetCanceled();
                    }
                    catch (InvalidOperationException exception)
                    {
                        // Already timeout
                        GC.KeepAlive(exception);
                    }
                }
                );
            }
            return(source.Task);
        }
Esempio n. 2
0
        public static Task <TResult> Then <T, TResult>(this Task <T> task, Func <T, Task <TResult> > onFulfilled)
        {
            task.NotNull(nameof(task));
            onFulfilled.NotNull(nameof(onFulfilled));

            if (task.IsCompleted)
            {
                if (task.Exception?.InnerException != null)
                {
                    return(Promise.Reject <TResult>(task.Exception.InnerExceptions));
                }
                if (task.IsCanceled)
                {
                    return(Promise.Cancel <TResult>());
                }

                try
                {
                    return(onFulfilled(task.Result));
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    return(Promise.Reject <TResult>(e));
                }
            }

            var tcs = new TaskCompletionSource <TResult>();

            task.ContinueWith(t =>
            {
                if (t.Exception?.InnerException != null)
                {
                    tcs.SetException(t.Exception.InnerExceptions);
                    return;
                }

                if (t.IsCanceled)
                {
                    tcs.SetCanceled();
                    return;
                }

                Task <TResult> fulfilledTask;
                try
                {
                    fulfilledTask = onFulfilled(t.Result);
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    tcs.SetException(e);
                    return;
                }

                if (fulfilledTask.IsCompleted)
                {
                    tcs.SetFromCompleted(fulfilledTask);
                    return;
                }

                fulfilledTask.ContinueWith(
                    ft => tcs.SetFromCompleted(ft), CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
            }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

            return(tcs.Task);
        }
Esempio n. 3
0
 /// <summary>
 /// Transitions the underlying task into the <see cref="SystemTasks.TaskStatus.Canceled"/> state.
 /// </summary>
 public static void SetCanceled(SystemTaskCompletionSource tcs) => tcs.SetCanceled();
        public static Task Catch(this Task task, Func <Exception, Task> onRejected)
        {
            task.NotNull(nameof(task));
            onRejected.NotNull(nameof(onRejected));

            if (task.IsCompleted)
            {
                if (task.IsCanceled || task.Exception?.InnerException == null)
                {
                    return(task);
                }

                try
                {
                    return(onRejected(task.Exception.InnerException));
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    return(Promise.Reject(e));
                }
            }

            var tcs = new TaskCompletionSource <bool>();

            task.ContinueWith(t =>
            {
                if (t.Exception?.InnerException == null)
                {
                    if (t.IsCanceled)
                    {
                        tcs.SetCanceled();
                        return;
                    }

                    tcs.SetResult(true);
                    return;
                }

                Task rejectedTask;
                try
                {
                    rejectedTask = onRejected(t.Exception.InnerException);
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    tcs.SetException(e);
                    return;
                }

                if (rejectedTask.IsCompleted)
                {
                    tcs.SetFromCompleted(rejectedTask);
                    return;
                }

                rejectedTask.ContinueWith(
                    rt => tcs.SetFromCompleted(rt), CancellationToken.None,
                    TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
            }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

            return(tcs.Task);
        }
        public static Task <T> Finally <T>(this Task <T> task, Func <Task> onFinally)
        {
            task.NotNull(nameof(task));
            onFinally.NotNull(nameof(onFinally));

            TaskCompletionSource <T> tcs;

            if (task.IsCompleted)
            {
                Task finallyTask;
                try
                {
                    finallyTask = onFinally();
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    return(Promise.Reject <T>(e));
                }

                if (finallyTask.IsCompleted)
                {
                    if (finallyTask.Exception?.InnerException != null)
                    {
                        return(Promise.Reject <T>(finallyTask.Exception.InnerExceptions));
                    }

                    return(finallyTask.IsCanceled ? Promise.Cancel <T>() : task);
                }

                tcs = new TaskCompletionSource <T>();

                finallyTask.ContinueWith(ft =>
                {
                    if (ft.Exception?.InnerException != null)
                    {
                        tcs.SetException(ft.Exception.InnerExceptions);
                        return;
                    }

                    if (ft.IsCanceled)
                    {
                        tcs.SetCanceled();
                        return;
                    }

                    tcs.SetFromCompleted(task);
                }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

                return(tcs.Task);
            }

            tcs = new TaskCompletionSource <T>();

            task.ContinueWith(t =>
            {
                Task finallyTask;
                try
                {
                    finallyTask = onFinally();
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    tcs.SetException(e);
                    return;
                }

                if (finallyTask.IsCompleted)
                {
                    if (finallyTask.Exception?.InnerException != null)
                    {
                        tcs.SetException(finallyTask.Exception.InnerExceptions);
                        return;
                    }

                    if (finallyTask.IsCanceled)
                    {
                        tcs.SetCanceled();
                        return;
                    }

                    tcs.SetFromCompleted(t);
                    return;
                }

                finallyTask.ContinueWith(ft =>
                {
                    if (ft.Exception?.InnerException != null)
                    {
                        tcs.SetException(ft.Exception.InnerExceptions);
                        return;
                    }

                    if (ft.IsCanceled)
                    {
                        tcs.SetCanceled();
                        return;
                    }

                    tcs.SetFromCompleted(t);
                }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
            }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

            return(tcs.Task);
        }