public static Task Finally(this Task task, Action onFinally)
        {
            task.NotNull(nameof(task));
            onFinally.NotNull(nameof(onFinally));

            if (task.IsCompleted)
            {
                try
                {
                    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(e));
                }

                return(task);
            }

            var tcs = new TaskCompletionSource <bool>();

            task.ContinueWith(t =>
            {
                try
                {
                    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;
                }

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

            return(tcs.Task);
        }
Example #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);
        }
        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);
        }