using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Pithos.Core { public static class TaskExtensions { public static Task Then(this Task first, Func> next) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); Contract.EndContractBlock(); return Then(first, next, CancellationToken.None); } public static Task Then(this Task first, Func next) { if (first == null) throw new ArgumentNullException("first"); if (next == null) throw new ArgumentNullException("next"); Contract.EndContractBlock(); 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"); Contract.EndContractBlock(); Contract.Assume(TaskScheduler.Current!=null); 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"); Contract.EndContractBlock(); Contract.Assume(TaskScheduler.Current != null); 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(); } } public static bool TryRemove(this ObservableConcurrentCollection collection,T item) where T:class { IProducerConsumerCollection items= collection; for (var i = 0; i < items.Count; i++) { T tempItem; if (!items.TryTake(out tempItem)) return false; if (tempItem == item) return true; items.TryAdd(item); } return false; } } }