You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Lidarr/src/Microsoft.AspNet.SignalR.Core/TaskAsyncHelper.cs

1115 lines
41 KiB

// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.SignalR
{
internal static class TaskAsyncHelper
{
private static readonly Task _emptyTask = MakeTask<object>(null);
private static readonly Task<bool> _trueTask = MakeTask<bool>(true);
private static readonly Task<bool> _falseTask = MakeTask<bool>(false);
private static Task<T> MakeTask<T>(T value)
{
return FromResult<T>(value);
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Empty
{
get
{
return _emptyTask;
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<bool> True
{
get
{
return _trueTask;
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<bool> False
{
get
{
return _falseTask;
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task OrEmpty(this Task task)
{
return task ?? Empty;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<T> OrEmpty<T>(this Task<T> task)
{
return task ?? TaskCache<T>.Empty;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task FromAsync(Func<AsyncCallback, object, IAsyncResult> beginMethod, Action<IAsyncResult> endMethod, object state)
{
try
{
return Task.Factory.FromAsync(beginMethod, endMethod, state);
}
catch (Exception ex)
{
return TaskAsyncHelper.FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task<T> FromAsync<T>(Func<AsyncCallback, object, IAsyncResult> beginMethod, Func<IAsyncResult, T> endMethod, object state)
{
try
{
return Task.Factory.FromAsync<T>(beginMethod, endMethod, state);
}
catch (Exception ex)
{
return TaskAsyncHelper.FromError<T>(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Series(Func<object, Task>[] tasks, object[] state)
{
Task prev = TaskAsyncHelper.Empty;
Task finalTask = TaskAsyncHelper.Empty;
for (int i = 0; i < tasks.Length; i++)
{
prev = finalTask;
finalTask = prev.Then(tasks[i], state[i]);
}
return finalTask;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static TTask Catch<TTask>(this TTask task) where TTask : Task
{
return Catch(task, ex => { });
}
#if PERFCOUNTERS
public static TTask Catch<TTask>(this TTask task, params IPerformanceCounter[] counters) where TTask : Task
{
return Catch(task, _ =>
{
if (counters == null)
{
return;
}
for (var i = 0; i < counters.Length; i++)
{
counters[i].Increment();
}
});
}
#endif
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static TTask Catch<TTask>(this TTask task, Action<AggregateException, object> handler, object state) where TTask : Task
{
if (task != null && task.Status != TaskStatus.RanToCompletion)
{
if (task.Status == TaskStatus.Faulted)
{
ExecuteOnFaulted(handler, state, task.Exception);
}
else
{
AttachFaultedContinuation<TTask>(task, handler, state);
}
}
return task;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
private static void AttachFaultedContinuation<TTask>(TTask task, Action<AggregateException, object> handler, object state) where TTask : Task
{
task.ContinueWith(innerTask =>
{
ExecuteOnFaulted(handler, state, innerTask.Exception);
},
TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
private static void ExecuteOnFaulted(Action<AggregateException, object> handler, object state, AggregateException exception)
{
// observe Exception
#if !WINDOWS_PHONE && !SILVERLIGHT && !NETFX_CORE
Trace.TraceError("SignalR exception thrown by Task: {0}", exception);
#endif
handler(exception, state);
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static TTask Catch<TTask>(this TTask task, Action<AggregateException> handler) where TTask : Task
{
return task.Catch((ex, state) => ((Action<AggregateException>)state).Invoke(ex),
handler);
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task ContinueWithNotComplete(this Task task, Action action)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
try
{
action();
return task;
}
catch (Exception e)
{
return FromError(e);
}
case TaskStatus.RanToCompletion:
return task;
default:
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
try
{
action();
if (t.IsFaulted)
{
tcs.TrySetUnwrappedException(t.Exception);
}
else
{
tcs.TrySetCanceled();
}
}
catch (Exception e)
{
tcs.TrySetException(e);
}
}
else
{
tcs.TrySetResult(null);
}
},
TaskContinuationOptions.ExecuteSynchronously);
return tcs.Task;
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static void ContinueWithNotComplete(this Task task, TaskCompletionSource<object> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetUnwrappedException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
},
TaskContinuationOptions.NotOnRanToCompletion);
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static void ContinueWith(this Task task, TaskCompletionSource<object> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.TrySetUnwrappedException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(null);
}
},
TaskContinuationOptions.ExecuteSynchronously);
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static void ContinueWith<T>(this Task<T> task, TaskCompletionSource<T> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.TrySetUnwrappedException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(t.Result);
}
});
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Return(this Task[] tasks)
{
return Then(tasks, () => { });
}
// Then extesions
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then(this Task task, Action successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor);
default:
return RunTask(task, successor);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<TResult> Then<TResult>(this Task task, Func<TResult> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError<TResult>(task.Exception);
case TaskStatus.Canceled:
return Canceled<TResult>();
case TaskStatus.RanToCompletion:
return FromMethod(successor);
default:
return TaskRunners<object, TResult>.RunTask(task, successor);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then(this Task[] tasks, Action successor)
{
if (tasks.Length == 0)
{
return FromMethod(successor);
}
var tcs = new TaskCompletionSource<object>();
Task.Factory.ContinueWhenAll(tasks, completedTasks =>
{
var faulted = completedTasks.FirstOrDefault(t => t.IsFaulted);
if (faulted != null)
{
tcs.SetUnwrappedException(faulted.Exception);
return;
}
var cancelled = completedTasks.FirstOrDefault(t => t.IsCanceled);
if (cancelled != null)
{
tcs.SetCanceled();
return;
}
successor();
tcs.SetResult(null);
});
return tcs.Task;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then<T1>(this Task task, Action<T1> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1);
default:
return GenericDelegates<object, object, T1, object>.ThenWithArgs(task, successor, arg1);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then<T1, T2>(this Task task, Action<T1, T2> successor, T1 arg1, T2 arg2)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1, arg2);
default:
return GenericDelegates<object, object, T1, T2>.ThenWithArgs(task, successor, arg1, arg2);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then<T1>(this Task task, Func<T1, Task> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1);
default:
return GenericDelegates<object, Task, T1, object>.ThenWithArgs(task, successor, arg1)
.FastUnwrap();
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then<T1, T2>(this Task task, Func<T1, T2, Task> successor, T1 arg1, T2 arg2)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1, arg2);
default:
return GenericDelegates<object, Task, T1, T2>.ThenWithArgs(task, successor, arg1, arg2)
.FastUnwrap();
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<TResult> Then<T, TResult>(this Task<T> task, Func<T, Task<TResult>> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError<TResult>(task.Exception);
case TaskStatus.Canceled:
return Canceled<TResult>();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result);
default:
return TaskRunners<T, Task<TResult>>.RunTask(task, t => successor(t.Result))
.FastUnwrap();
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<TResult> Then<T, TResult>(this Task<T> task, Func<T, TResult> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError<TResult>(task.Exception);
case TaskStatus.Canceled:
return Canceled<TResult>();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result);
default:
return TaskRunners<T, TResult>.RunTask(task, t => successor(t.Result));
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<TResult> Then<T, T1, TResult>(this Task<T> task, Func<T, T1, TResult> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError<TResult>(task.Exception);
case TaskStatus.Canceled:
return Canceled<TResult>();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result, arg1);
default:
return GenericDelegates<T, TResult, T1, object>.ThenWithArgs(task, successor, arg1);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then(this Task task, Func<Task> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor);
default:
return TaskRunners<object, Task>.RunTask(task, successor)
.FastUnwrap();
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<TResult> Then<TResult>(this Task task, Func<Task<TResult>> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError<TResult>(task.Exception);
case TaskStatus.Canceled:
return Canceled<TResult>();
case TaskStatus.RanToCompletion:
return FromMethod(successor);
default:
return TaskRunners<object, Task<TResult>>.RunTask(task, successor)
.FastUnwrap();
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then<TResult>(this Task<TResult> task, Action<TResult> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result);
default:
return TaskRunners<TResult, object>.RunTask(task, successor);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Then<TResult>(this Task<TResult> task, Func<TResult, Task> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result);
default:
return TaskRunners<TResult, Task>.RunTask(task, t => successor(t.Result))
.FastUnwrap();
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<TResult> Then<TResult, T1>(this Task<TResult> task, Func<Task<TResult>, T1, Task<TResult>> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor, task, arg1);
default:
return GenericDelegates<TResult, Task<TResult>, T1, object>.ThenWithArgs(task, successor, arg1)
.FastUnwrap();
}
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are flowed to the caller")]
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Finally(this Task task, Action<object> next, object state)
{
try
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
next(state);
return task;
case TaskStatus.RanToCompletion:
return FromMethod(next, state);
default:
return RunTaskSynchronously(task, next, state, onlyOnSuccess: false);
}
}
catch (Exception ex)
{
return FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task RunSynchronously(this Task task, Action successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
case TaskStatus.Canceled:
return task;
case TaskStatus.RanToCompletion:
return FromMethod(successor);
default:
return RunTaskSynchronously(task, state => ((Action)state).Invoke(), successor);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task FastUnwrap(this Task<Task> task)
{
var innerTask = (task.Status == TaskStatus.RanToCompletion) ? task.Result : null;
return innerTask ?? task.Unwrap();
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<T> FastUnwrap<T>(this Task<Task<T>> task)
{
var innerTask = (task.Status == TaskStatus.RanToCompletion) ? task.Result : null;
return innerTask ?? task.Unwrap();
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task Delay(TimeSpan timeOut)
{
#if NETFX_CORE
return Task.Delay(timeOut);
#else
var tcs = new TaskCompletionSource<object>();
var timer = new Timer(tcs.SetResult,
null,
timeOut,
TimeSpan.FromMilliseconds(-1));
return tcs.Task.ContinueWith(_ =>
{
timer.Dispose();
},
TaskContinuationOptions.ExecuteSynchronously);
#endif
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task FromMethod(Action func)
{
try
{
func();
return Empty;
}
catch (Exception ex)
{
return FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task FromMethod<T1>(Action<T1> func, T1 arg)
{
try
{
func(arg);
return Empty;
}
catch (Exception ex)
{
return FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task FromMethod<T1, T2>(Action<T1, T2> func, T1 arg1, T2 arg2)
{
try
{
func(arg1, arg2);
return Empty;
}
catch (Exception ex)
{
return FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task FromMethod(Func<Task> func)
{
try
{
return func();
}
catch (Exception ex)
{
return FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task<TResult> FromMethod<TResult>(Func<Task<TResult>> func)
{
try
{
return func();
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task<TResult> FromMethod<TResult>(Func<TResult> func)
{
try
{
return FromResult<TResult>(func());
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task FromMethod<T1>(Func<T1, Task> func, T1 arg)
{
try
{
return func(arg);
}
catch (Exception ex)
{
return FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task FromMethod<T1, T2>(Func<T1, T2, Task> func, T1 arg1, T2 arg2)
{
try
{
return func(arg1, arg2);
}
catch (Exception ex)
{
return FromError(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task<TResult> FromMethod<T1, TResult>(Func<T1, Task<TResult>> func, T1 arg)
{
try
{
return func(arg);
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task<TResult> FromMethod<T1, TResult>(Func<T1, TResult> func, T1 arg)
{
try
{
return FromResult<TResult>(func(arg));
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task<TResult> FromMethod<T1, T2, TResult>(Func<T1, T2, Task<TResult>> func, T1 arg1, T2 arg2)
{
try
{
return func(arg1, arg2);
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
public static Task<TResult> FromMethod<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 arg1, T2 arg2)
{
try
{
return FromResult<TResult>(func(arg1, arg2));
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
public static Task<T> FromResult<T>(T value)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(value);
return tcs.Task;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
internal static Task FromError(Exception e)
{
return FromError<object>(e);
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
internal static Task<T> FromError<T>(Exception e)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetUnwrappedException<T>(e);
return tcs.Task;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
internal static void SetUnwrappedException<T>(this TaskCompletionSource<T> tcs, Exception e)
{
var aggregateException = e as AggregateException;
if (aggregateException != null)
{
tcs.SetException(aggregateException.InnerExceptions);
}
else
{
tcs.SetException(e);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
internal static bool TrySetUnwrappedException<T>(this TaskCompletionSource<T> tcs, Exception e)
{
var aggregateException = e as AggregateException;
if (aggregateException != null)
{
return tcs.TrySetException(aggregateException.InnerExceptions);
}
else
{
return tcs.TrySetException(e);
}
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
private static Task Canceled()
{
var tcs = new TaskCompletionSource<object>();
tcs.SetCanceled();
return tcs.Task;
}
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
private static Task<T> Canceled<T>()
{
var tcs = new TaskCompletionSource<T>();
tcs.SetCanceled();
return tcs.Task;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
private static Task RunTask(Task task, Action successor)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetUnwrappedException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
successor();
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetUnwrappedException(ex);
}
}
});
return tcs.Task;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a shared file")]
private static Task RunTaskSynchronously(Task task, Action<object> next, object state, bool onlyOnSuccess = true)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
try
{
if (t.IsFaulted)
{
if (!onlyOnSuccess)
{
next(state);
}
tcs.SetUnwrappedException(t.Exception);
}
else if (t.IsCanceled)
{
if (!onlyOnSuccess)
{
next(state);
}
tcs.SetCanceled();
}
else
{
next(state);
tcs.SetResult(null);
}
}
catch (Exception ex)
{
tcs.SetUnwrappedException(ex);
}
},
TaskContinuationOptions.ExecuteSynchronously);
return tcs.Task;
}
private static class TaskRunners<T, TResult>
{
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
internal static Task RunTask(Task<T> task, Action<T> successor)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetUnwrappedException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
successor(t.Result);
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetUnwrappedException(ex);
}
}
});
return tcs.Task;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
internal static Task<TResult> RunTask(Task task, Func<TResult> successor)
{
var tcs = new TaskCompletionSource<TResult>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetUnwrappedException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
tcs.SetResult(successor());
}
catch (Exception ex)
{
tcs.SetUnwrappedException(ex);
}
}
});
return tcs.Task;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Exceptions are set in a tcs")]
internal static Task<TResult> RunTask(Task<T> task, Func<Task<T>, TResult> successor)
{
var tcs = new TaskCompletionSource<TResult>();
task.ContinueWith(t =>
{
if (task.IsFaulted)
{
tcs.SetUnwrappedException(t.Exception);
}
else if (task.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
tcs.SetResult(successor(t));
}
catch (Exception ex)
{
tcs.SetUnwrappedException(ex);
}
}
});
return tcs.Task;
}
}
private static class GenericDelegates<T, TResult, T1, T2>
{
internal static Task ThenWithArgs(Task task, Action<T1> successor, T1 arg1)
{
return RunTask(task, () => successor(arg1));
}
internal static Task ThenWithArgs(Task task, Action<T1, T2> successor, T1 arg1, T2 arg2)
{
return RunTask(task, () => successor(arg1, arg2));
}
internal static Task<TResult> ThenWithArgs(Task task, Func<T1, TResult> successor, T1 arg1)
{
return TaskRunners<object, TResult>.RunTask(task, () => successor(arg1));
}
internal static Task<TResult> ThenWithArgs(Task task, Func<T1, T2, TResult> successor, T1 arg1, T2 arg2)
{
return TaskRunners<object, TResult>.RunTask(task, () => successor(arg1, arg2));
}
internal static Task<TResult> ThenWithArgs(Task<T> task, Func<T, T1, TResult> successor, T1 arg1)
{
return TaskRunners<T, TResult>.RunTask(task, t => successor(t.Result, arg1));
}
internal static Task<Task> ThenWithArgs(Task task, Func<T1, Task> successor, T1 arg1)
{
return TaskRunners<object, Task>.RunTask(task, () => successor(arg1));
}
internal static Task<Task> ThenWithArgs(Task task, Func<T1, T2, Task> successor, T1 arg1, T2 arg2)
{
return TaskRunners<object, Task>.RunTask(task, () => successor(arg1, arg2));
}
internal static Task<Task<TResult>> ThenWithArgs(Task<T> task, Func<T, T1, Task<TResult>> successor, T1 arg1)
{
return TaskRunners<T, Task<TResult>>.RunTask(task, t => successor(t.Result, arg1));
}
internal static Task<Task<T>> ThenWithArgs(Task<T> task, Func<Task<T>, T1, Task<T>> successor, T1 arg1)
{
return TaskRunners<T, Task<T>>.RunTask(task, t => successor(t, arg1));
}
}
private static class TaskCache<T>
{
public static Task<T> Empty = MakeTask<T>(default(T));
}
}
}