using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Pithos.Core { static class TaskExtensions { public static Task Then(this Task first, Func> next) { return Then(first, next, CancellationToken.None); } public static Task Then(this Task first, Func next) { return Then(first, next, CancellationToken.None); } public static Task Then(this Task first, Func> next, CancellationToken cancellationToken) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); var tcs = new TaskCompletionSource(); first.ContinueWith(delegate { if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions); else if (first.IsCanceled) tcs.TrySetCanceled(); else { try { var t = next(first.Result); if (t == null) tcs.TrySetCanceled(); else t.ContinueWith(delegate { if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions); else if (t.IsCanceled) tcs.TrySetCanceled(); else tcs.TrySetResult(t.Result); }, TaskContinuationOptions.ExecuteSynchronously); } catch (Exception exc) { tcs.TrySetException(exc); } } }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current); return tcs.Task; } public static Task Then(this Task first, Func next, CancellationToken cancellationToken) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); var tcs = new TaskCompletionSource(); first.ContinueWith(delegate { if (first.IsFaulted) tcs.TrySetException(first.Exception.InnerExceptions); else if (first.IsCanceled) tcs.TrySetCanceled(); else { try { var t = next(first.Result); if (t == null) tcs.TrySetCanceled(); else t.ContinueWith(delegate { if (t.IsFaulted) tcs.TrySetException(t.Exception.InnerExceptions); else if (t.IsCanceled) tcs.TrySetCanceled(); else tcs.TrySetResult(null); }, TaskContinuationOptions.ExecuteSynchronously); } catch (Exception exc) { tcs.TrySetException(exc); } } }, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Current); return tcs.Task; } public static void ReportExceptions(this Task task,Action OnError,Action OnSuccess ) { if (!task.IsCompleted) throw new InvalidOperationException("The task has not completed."); if (task.IsFaulted) task.Exception.Handle(exc=> { OnError(task.Exception); return true; }); else { OnSuccess(); } } } }