/** * A version using TaskCompletionSource and task continuations * Not much better. */ public static Task <D> RunTasks2Async(TAPServices svc) { TaskCompletionSource <D> promise = new TaskCompletionSource <D>(); svc.Oper1Async(). ContinueWith(ant => { if (ant.IsFaulted) { promise.SetException(ant.Exception); return; } Task <B> tb = svc.Oper2Async(ant.Result); Task <C> tc = svc.Oper3Async(ant.Result); Task.WhenAll(tb, tc). ContinueWith(ant2 => { if (ant2.IsFaulted) { promise.SetException(ant2.Exception); return; } svc.Oper4Async(tb.Result, tc.Result). ContinueWith(ant3 => { if (ant2.IsFaulted) { promise.SetException(ant.Exception); } else { promise.SetResult(ant3.Result); } }); }); }); return(promise.Task); }
/** * Using ThenCompose and ThenCombine combinators. * Much better, but needs an auxiliary type */ public static Task <D> RunTasks3Async(TAPServices svc) { return (svc.Oper1Async(). ThenCompose((A a) => { return svc.Oper2Async(a) .ThenCombine(svc.Oper3Async(a), (b, c) => new BC(b, c)) .ThenCompose((bc) => svc.Oper4Async(bc.b, bc.c)); })); }
/** * Using an async C# method */ public static async Task <D> RunAsync(TAPServices svc) { A a = await svc.Oper1Async(); Task <B> tb = svc.Oper2Async(a); Task <C> tc = svc.Oper3Async(a); await Task.WhenAll(tb, tc); return(await svc.Oper4Async(tb.Result, tc.Result)); }
/** * A version using Task continuations. * * Very convoluted, indeed. */ public static Task <D> RunTasksAsync(TAPServices svc) { return(svc.Oper1Async(). ContinueWith(ant => { Task <B> tb = svc.Oper2Async(ant.Result); Task <C> tc = svc.Oper3Async(ant.Result); return Task.WhenAll(tb, tc). ContinueWith(ant2 => { return svc.Oper4Async(tb.Result, tc.Result); }). Unwrap(); }) .Unwrap()); }