namespace Microshaoft
{
using System;
using System.Threading.Tasks;
using System.Web;
public class HttpTaskAsyncHandler : IHttpAsyncHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
throw new NotSupportedException();
}
public Task ProcessRequestAsync(HttpContextBase context)
{
// Microshaoft.
//TaskAsyncHelper.
return null;
}
IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
Task task = ProcessRequestAsync(new HttpContextWrapper(context));
var retVal = new TaskWrapperAsyncResult(task, extraData);
if (task == null)
{
// No task, so just let ASP.NET deal with it
return null;
}
if (cb != null)
{
// The callback needs the same argument that the Begin method returns, which is our special wrapper, not the original Task.
task.ContinueWith(_ => cb(retVal));
}
return retVal;
}
void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
// The End* method doesn't actually perform any actual work, but we do need to maintain two invariants:
// 1. Make sure the underlying Task actually *is* complete.
// 2. If the Task encountered an exception, observe it here.
// (The Wait method handles both of those.)
var castResult = (TaskWrapperAsyncResult)result;
castResult.Task.Wait();
}
}
}
namespace Microshaoft
{
using System;
using System.Threading;
using System.Threading.Tasks;
internal sealed class TaskWrapperAsyncResult : IAsyncResult
{
internal TaskWrapperAsyncResult(Task task, object asyncState)
{
Task = task;
AsyncState = asyncState;
}
public object AsyncState
{
get;
private set;
}
public WaitHandle AsyncWaitHandle
{
get { return ((IAsyncResult)Task).AsyncWaitHandle; }
}
public bool CompletedSynchronously
{
get { return ((IAsyncResult)Task).CompletedSynchronously; }
}
public bool IsCompleted
{
get { return ((IAsyncResult)Task).IsCompleted; }
}
public Task Task
{
get;
private set;
}
}
}
namespace Microshaoft
{
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
public static class TaskAsyncHelper
{
private static readonly Task _emptyTask = MakeEmpty();
private static Task MakeEmpty()
{
return FromResult<object>(null);
}
public static Task Empty
{
get
{
return _emptyTask;
}
}
public static TTask Catch<TTask>(this TTask task) where TTask : Task
{
if (task != null && task.Status != TaskStatus.RanToCompletion)
{
task.ContinueWith(innerTask =>
{
var ex = innerTask.Exception;
// observe Exception
#if !WINDOWS_PHONE && !SILVERLIGHT && !NETFX_CORE
Trace.TraceError("SignalR exception thrown by Task: {0}", ex);
#endif
}, TaskContinuationOptions.OnlyOnFaulted);
}
return task;
}
public static TTask Catch<TTask>(this TTask task, Action<Exception> handler) where TTask : Task
{
if (task != null && task.Status != TaskStatus.RanToCompletion)
{
task.ContinueWith(innerTask =>
{
var ex = innerTask.Exception;
// observe Exception
#if !WINDOWS_PHONE && !SILVERLIGHT && !NETFX_CORE
Trace.TraceError("SignalR exception thrown by Task: {0}", ex);
#endif
handler(ex);
}, TaskContinuationOptions.OnlyOnFaulted);
}
return task;
}
public static void ContinueWithNotComplete(this Task task, TaskCompletionSource<object> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
},
TaskContinuationOptions.NotOnRanToCompletion);
}
public static void ContinueWith(this Task task, TaskCompletionSource<object> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.TrySetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(null);
}
});
}
public static void ContinueWith<T>(this Task<T> task, TaskCompletionSource<T> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.TrySetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(t.Result);
}
});
}
/// <summary>
/// Passes a task returning function into another task returning function so that
/// it can decide when it starts and returns a task that completes when all are finished
/// </summary>
public static Task Interleave<T>(Func<T, Action, Task> before, Func<Task> after, T arg)
{
var tcs = new TaskCompletionSource<object>();
var tasks = new[] {
tcs.Task,
before(arg, () => after().ContinueWith(tcs))
};
return tasks.Return();
}
public static Task Return(this Task[] tasks)
{
return Then(tasks, () => { });
}
// Then extesions
public static Task Then(this Task task, Action successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor);
default:
return RunTask(task, successor);
}
}
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);
}
}
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.SetException(faulted.Exception);
return;
}
var cancelled = completedTasks.FirstOrDefault(t => t.IsCanceled);
if (cancelled != null)
{
tcs.SetCanceled();
return;
}
successor();
tcs.SetResult(null);
});
return tcs.Task;
}
public static Task Then<T1>(this Task task, Action<T1> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1);
default:
return GenericDelegates<object, object, T1, object>.ThenWithArgs(task, successor, arg1);
}
}
public static Task Then<T1, T2>(this Task task, Action<T1, T2> successor, T1 arg1, T2 arg2)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1, arg2);
default:
return GenericDelegates<object, object, T1, T2>.ThenWithArgs(task, successor, arg1, arg2);
}
}
public static Task Then<T1>(this Task task, Func<T1, Task> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1).FastUnwrap();
default:
return GenericDelegates<object, Task, T1, object>.ThenWithArgs(task, successor, arg1)
.FastUnwrap();
}
}
public static Task Then<T1, T2>(this Task task, Func<T1, T2, Task> successor, T1 arg1, T2 arg2)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1, arg2).FastUnwrap();
default:
return GenericDelegates<object, Task, T1, T2>.ThenWithArgs(task, successor, arg1, arg2)
.FastUnwrap();
}
}
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).FastUnwrap();
default:
return TaskRunners<T, Task<TResult>>.RunTask(task, t => successor(t.Result))
.FastUnwrap();
}
}
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));
}
}
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);
}
}
public static Task Then(this Task task, Func<Task> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor).FastUnwrap();
default:
return TaskRunners<object, Task>.RunTask(task, successor)
.FastUnwrap();
}
}
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).FastUnwrap();
default:
return TaskRunners<object, Task<TResult>>.RunTask(task, successor)
.FastUnwrap();
}
}
public static Task Then<TResult>(this Task<TResult> task, Action<TResult> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result);
default:
return TaskRunners<TResult, object>.RunTask(task, successor);
}
}
public static Task Then<TResult>(this Task<TResult> task, Func<TResult, Task> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result).FastUnwrap();
default:
return TaskRunners<TResult, Task>.RunTask(task, t => successor(t.Result))
.FastUnwrap();
}
}
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:
return FromError<TResult>(task.Exception);
case TaskStatus.Canceled:
return Canceled<TResult>();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task, arg1).FastUnwrap();
default:
return GenericDelegates<TResult, Task<TResult>, T1, object>.ThenWithArgs(task, successor, arg1)
.FastUnwrap();
}
}
public static Task FastUnwrap(this Task<Task> task)
{
var innerTask = (task.Status == TaskStatus.RanToCompletion) ? task.Result : null;
return innerTask ?? task.Unwrap();
}
public static Task<T> FastUnwrap<T>(this Task<Task<T>> task)
{
var innerTask = (task.Status == TaskStatus.RanToCompletion) ? task.Result : null;
return innerTask ?? task.Unwrap();
}
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
}
public static Task AllSucceeded(this Task[] tasks, Action continuation)
{
return AllSucceeded(tasks, _ => continuation());
}
public static Task AllSucceeded(this Task[] tasks, Action<Task[]> continuation)
{
return Task.Factory.ContinueWhenAll(tasks, _ =>
{
var cancelledTask = tasks.FirstOrDefault(task => task.IsCanceled);
if (cancelledTask != null)
throw new TaskCanceledException();
var allExceptions =
tasks.Where(task => task.IsFaulted).SelectMany(task => task.Exception.InnerExceptions).ToList();
if (allExceptions.Count > 0)
{
throw new AggregateException(allExceptions);
}
continuation(tasks);
});
}
public static Task FromMethod(Action func)
{
try
{
func();
return Empty;
}
catch (Exception ex)
{
return FromError(ex);
}
}
public static Task FromMethod<T1>(Action<T1> func, T1 arg)
{
try
{
func(arg);
return Empty;
}
catch (Exception ex)
{
return FromError(ex);
}
}
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);
}
}
public static Task<TResult> FromMethod<TResult>(Func<TResult> func)
{
try
{
return FromResult<TResult>(func());
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
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);
}
}
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);
}
}
public static Task<T> FromResult<T>(T value)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(value);
return tcs.Task;
}
#if !NETFX_CORE
public static TaskContinueWithMethod GetContinueWith(Type taskType)
{
var continueWith = (from m in taskType.GetMethods()
let methodParameters = m.GetParameters()
where m.Name.Equals("ContinueWith", StringComparison.OrdinalIgnoreCase) &&
methodParameters.Length == 1
let parameter = methodParameters[0]
where parameter.ParameterType.IsGenericType &&
typeof(Func<,>) == parameter.ParameterType.GetGenericTypeDefinition()
select new TaskContinueWithMethod
{
Method = m.MakeGenericMethod(typeof(Task)),
Type = parameter.ParameterType.GetGenericArguments()[0]
})
.FirstOrDefault();
return continueWith;
}
#endif
internal static Task FromError(Exception e)
{
var tcs = new TaskCompletionSource<object>();
tcs.SetException(e);
return tcs.Task;
}
internal static Task<T> FromError<T>(Exception e)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetException(e);
return tcs.Task;
}
private static Task Canceled()
{
var tcs = new TaskCompletionSource<object>();
tcs.SetCanceled();
return tcs.Task;
}
private static Task<T> Canceled<T>()
{
var tcs = new TaskCompletionSource<T>();
tcs.SetCanceled();
return tcs.Task;
}
public class TaskContinueWithMethod
{
public MethodInfo Method { get; set; }
public Type Type { get; set; }
}
private static Task RunTask(Task task, Action successor)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
successor();
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
});
return tcs.Task;
}
private static class TaskRunners<T, TResult>
{
internal static Task RunTask(Task<T> task, Action<T> successor)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
successor(t.Result);
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
});
return tcs.Task;
}
internal static Task<TResult> RunTask(Task task, Func<TResult> successor)
{
var tcs = new TaskCompletionSource<TResult>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
tcs.SetResult(successor());
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
});
return tcs.Task;
}
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.SetException(t.Exception);
}
else if (task.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
tcs.SetResult(successor(t));
}
catch (Exception ex)
{
tcs.SetException(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<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));
}
}
}
}
namespace Microshaoft
{
using System;
using System.Threading.Tasks;
using System.Web;
public class HttpTaskAsyncHandler : IHttpAsyncHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
throw new NotSupportedException();
}
public Task ProcessRequestAsync(HttpContextBase context)
{
// Microshaoft.
//TaskAsyncHelper.
return null;
}
IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
Task task = ProcessRequestAsync(new HttpContextWrapper(context));
var retVal = new TaskWrapperAsyncResult(task, extraData);
if (task == null)
{
// No task, so just let ASP.NET deal with it
return null;
}
if (cb != null)
{
// The callback needs the same argument that the Begin method returns, which is our special wrapper, not the original Task.
task.ContinueWith(_ => cb(retVal));
}
return retVal;
}
void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
{
if (result == null)
{
throw new ArgumentNullException("result");
}
// The End* method doesn't actually perform any actual work, but we do need to maintain two invariants:
// 1. Make sure the underlying Task actually *is* complete.
// 2. If the Task encountered an exception, observe it here.
// (The Wait method handles both of those.)
var castResult = (TaskWrapperAsyncResult)result;
castResult.Task.Wait();
}
}
}
namespace Microshaoft
{
using System;
using System.Threading;
using System.Threading.Tasks;
internal sealed class TaskWrapperAsyncResult : IAsyncResult
{
internal TaskWrapperAsyncResult(Task task, object asyncState)
{
Task = task;
AsyncState = asyncState;
}
public object AsyncState
{
get;
private set;
}
public WaitHandle AsyncWaitHandle
{
get { return ((IAsyncResult)Task).AsyncWaitHandle; }
}
public bool CompletedSynchronously
{
get { return ((IAsyncResult)Task).CompletedSynchronously; }
}
public bool IsCompleted
{
get { return ((IAsyncResult)Task).IsCompleted; }
}
public Task Task
{
get;
private set;
}
}
}
namespace Microshaoft
{
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
public static class TaskAsyncHelper
{
private static readonly Task _emptyTask = MakeEmpty();
private static Task MakeEmpty()
{
return FromResult<object>(null);
}
public static Task Empty
{
get
{
return _emptyTask;
}
}
public static TTask Catch<TTask>(this TTask task) where TTask : Task
{
if (task != null && task.Status != TaskStatus.RanToCompletion)
{
task.ContinueWith(innerTask =>
{
var ex = innerTask.Exception;
// observe Exception
#if !WINDOWS_PHONE && !SILVERLIGHT && !NETFX_CORE
Trace.TraceError("SignalR exception thrown by Task: {0}", ex);
#endif
}, TaskContinuationOptions.OnlyOnFaulted);
}
return task;
}
public static TTask Catch<TTask>(this TTask task, Action<Exception> handler) where TTask : Task
{
if (task != null && task.Status != TaskStatus.RanToCompletion)
{
task.ContinueWith(innerTask =>
{
var ex = innerTask.Exception;
// observe Exception
#if !WINDOWS_PHONE && !SILVERLIGHT && !NETFX_CORE
Trace.TraceError("SignalR exception thrown by Task: {0}", ex);
#endif
handler(ex);
}, TaskContinuationOptions.OnlyOnFaulted);
}
return task;
}
public static void ContinueWithNotComplete(this Task task, TaskCompletionSource<object> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
},
TaskContinuationOptions.NotOnRanToCompletion);
}
public static void ContinueWith(this Task task, TaskCompletionSource<object> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.TrySetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(null);
}
});
}
public static void ContinueWith<T>(this Task<T> task, TaskCompletionSource<T> tcs)
{
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.TrySetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(t.Result);
}
});
}
/// <summary>
/// Passes a task returning function into another task returning function so that
/// it can decide when it starts and returns a task that completes when all are finished
/// </summary>
public static Task Interleave<T>(Func<T, Action, Task> before, Func<Task> after, T arg)
{
var tcs = new TaskCompletionSource<object>();
var tasks = new[] {
tcs.Task,
before(arg, () => after().ContinueWith(tcs))
};
return tasks.Return();
}
public static Task Return(this Task[] tasks)
{
return Then(tasks, () => { });
}
// Then extesions
public static Task Then(this Task task, Action successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor);
default:
return RunTask(task, successor);
}
}
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);
}
}
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.SetException(faulted.Exception);
return;
}
var cancelled = completedTasks.FirstOrDefault(t => t.IsCanceled);
if (cancelled != null)
{
tcs.SetCanceled();
return;
}
successor();
tcs.SetResult(null);
});
return tcs.Task;
}
public static Task Then<T1>(this Task task, Action<T1> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1);
default:
return GenericDelegates<object, object, T1, object>.ThenWithArgs(task, successor, arg1);
}
}
public static Task Then<T1, T2>(this Task task, Action<T1, T2> successor, T1 arg1, T2 arg2)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1, arg2);
default:
return GenericDelegates<object, object, T1, T2>.ThenWithArgs(task, successor, arg1, arg2);
}
}
public static Task Then<T1>(this Task task, Func<T1, Task> successor, T1 arg1)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1).FastUnwrap();
default:
return GenericDelegates<object, Task, T1, object>.ThenWithArgs(task, successor, arg1)
.FastUnwrap();
}
}
public static Task Then<T1, T2>(this Task task, Func<T1, T2, Task> successor, T1 arg1, T2 arg2)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, arg1, arg2).FastUnwrap();
default:
return GenericDelegates<object, Task, T1, T2>.ThenWithArgs(task, successor, arg1, arg2)
.FastUnwrap();
}
}
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).FastUnwrap();
default:
return TaskRunners<T, Task<TResult>>.RunTask(task, t => successor(t.Result))
.FastUnwrap();
}
}
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));
}
}
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);
}
}
public static Task Then(this Task task, Func<Task> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor).FastUnwrap();
default:
return TaskRunners<object, Task>.RunTask(task, successor)
.FastUnwrap();
}
}
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).FastUnwrap();
default:
return TaskRunners<object, Task<TResult>>.RunTask(task, successor)
.FastUnwrap();
}
}
public static Task Then<TResult>(this Task<TResult> task, Action<TResult> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result);
default:
return TaskRunners<TResult, object>.RunTask(task, successor);
}
}
public static Task Then<TResult>(this Task<TResult> task, Func<TResult, Task> successor)
{
switch (task.Status)
{
case TaskStatus.Faulted:
return FromError(task.Exception);
case TaskStatus.Canceled:
return Canceled();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task.Result).FastUnwrap();
default:
return TaskRunners<TResult, Task>.RunTask(task, t => successor(t.Result))
.FastUnwrap();
}
}
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:
return FromError<TResult>(task.Exception);
case TaskStatus.Canceled:
return Canceled<TResult>();
case TaskStatus.RanToCompletion:
return FromMethod(successor, task, arg1).FastUnwrap();
default:
return GenericDelegates<TResult, Task<TResult>, T1, object>.ThenWithArgs(task, successor, arg1)
.FastUnwrap();
}
}
public static Task FastUnwrap(this Task<Task> task)
{
var innerTask = (task.Status == TaskStatus.RanToCompletion) ? task.Result : null;
return innerTask ?? task.Unwrap();
}
public static Task<T> FastUnwrap<T>(this Task<Task<T>> task)
{
var innerTask = (task.Status == TaskStatus.RanToCompletion) ? task.Result : null;
return innerTask ?? task.Unwrap();
}
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
}
public static Task AllSucceeded(this Task[] tasks, Action continuation)
{
return AllSucceeded(tasks, _ => continuation());
}
public static Task AllSucceeded(this Task[] tasks, Action<Task[]> continuation)
{
return Task.Factory.ContinueWhenAll(tasks, _ =>
{
var cancelledTask = tasks.FirstOrDefault(task => task.IsCanceled);
if (cancelledTask != null)
throw new TaskCanceledException();
var allExceptions =
tasks.Where(task => task.IsFaulted).SelectMany(task => task.Exception.InnerExceptions).ToList();
if (allExceptions.Count > 0)
{
throw new AggregateException(allExceptions);
}
continuation(tasks);
});
}
public static Task FromMethod(Action func)
{
try
{
func();
return Empty;
}
catch (Exception ex)
{
return FromError(ex);
}
}
public static Task FromMethod<T1>(Action<T1> func, T1 arg)
{
try
{
func(arg);
return Empty;
}
catch (Exception ex)
{
return FromError(ex);
}
}
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);
}
}
public static Task<TResult> FromMethod<TResult>(Func<TResult> func)
{
try
{
return FromResult<TResult>(func());
}
catch (Exception ex)
{
return FromError<TResult>(ex);
}
}
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);
}
}
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);
}
}
public static Task<T> FromResult<T>(T value)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(value);
return tcs.Task;
}
#if !NETFX_CORE
public static TaskContinueWithMethod GetContinueWith(Type taskType)
{
var continueWith = (from m in taskType.GetMethods()
let methodParameters = m.GetParameters()
where m.Name.Equals("ContinueWith", StringComparison.OrdinalIgnoreCase) &&
methodParameters.Length == 1
let parameter = methodParameters[0]
where parameter.ParameterType.IsGenericType &&
typeof(Func<,>) == parameter.ParameterType.GetGenericTypeDefinition()
select new TaskContinueWithMethod
{
Method = m.MakeGenericMethod(typeof(Task)),
Type = parameter.ParameterType.GetGenericArguments()[0]
})
.FirstOrDefault();
return continueWith;
}
#endif
internal static Task FromError(Exception e)
{
var tcs = new TaskCompletionSource<object>();
tcs.SetException(e);
return tcs.Task;
}
internal static Task<T> FromError<T>(Exception e)
{
var tcs = new TaskCompletionSource<T>();
tcs.SetException(e);
return tcs.Task;
}
private static Task Canceled()
{
var tcs = new TaskCompletionSource<object>();
tcs.SetCanceled();
return tcs.Task;
}
private static Task<T> Canceled<T>()
{
var tcs = new TaskCompletionSource<T>();
tcs.SetCanceled();
return tcs.Task;
}
public class TaskContinueWithMethod
{
public MethodInfo Method { get; set; }
public Type Type { get; set; }
}
private static Task RunTask(Task task, Action successor)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
successor();
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
});
return tcs.Task;
}
private static class TaskRunners<T, TResult>
{
internal static Task RunTask(Task<T> task, Action<T> successor)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
successor(t.Result);
tcs.SetResult(null);
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
});
return tcs.Task;
}
internal static Task<TResult> RunTask(Task task, Func<TResult> successor)
{
var tcs = new TaskCompletionSource<TResult>();
task.ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception);
}
else if (t.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
tcs.SetResult(successor());
}
catch (Exception ex)
{
tcs.SetException(ex);
}
}
});
return tcs.Task;
}
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.SetException(t.Exception);
}
else if (task.IsCanceled)
{
tcs.SetCanceled();
}
else
{
try
{
tcs.SetResult(successor(t));
}
catch (Exception ex)
{
tcs.SetException(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<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));
}
}
}
}
|