Created
October 28, 2017 20:48
-
-
Save labaneilers/7b4ebc79c290c3e8f433010de5697397 to your computer and use it in GitHub Desktop.
Promises-link syntax for Tasks in dotnet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace exception_test | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Using promises"); | |
MainUsingPromises(args); | |
Console.WriteLine("Using traditional ContinueWith"); | |
MainUsingContinueWith(args); | |
} | |
static void MainUsingContinueWith(string[] args) | |
{ | |
RunAsync(GetStringCancelledLateAsync) | |
.ContinueWith(t => { | |
Console.WriteLine("debug: " + t.Result); | |
return t.Result + " has been added"; | |
}) | |
.ContinueWith(t => { | |
try | |
{ | |
Console.WriteLine("final: " + t.Result); | |
} | |
catch (AggregateException aex) | |
{ | |
aex.Flatten().Handle(ex => { | |
Console.WriteLine("agg error: " + ex.Message); | |
return true; | |
}); | |
} | |
}).Wait(); | |
} | |
static void MainUsingPromises(string[] args) | |
{ | |
RunAsync(GetStringAsync) | |
.Then(s => { | |
Console.WriteLine("debug: " + s); | |
return s + " has been added"; | |
}) | |
.Then(s => { | |
Console.WriteLine("final: " + s); | |
throw new Exception("More crazy"); | |
}) | |
.Catch(aex => { | |
aex.Handle(ex => { | |
Console.WriteLine("agg error: " + ex.Message); | |
return true; | |
}); | |
Console.WriteLine("error string"); | |
}) | |
.Wait(); | |
} | |
public static Task<string> GetStringAsync() | |
{ | |
return Task.Delay(500).ContinueWith(t => "hi"); | |
} | |
public static Task<string> ThrowExceptionLateAsync() | |
{ | |
return Task.Delay(500).ContinueWith<string>(t => { | |
throw new Exception("late"); | |
}); | |
} | |
public static Task<string> ThrowExceptionEarlyAsync() | |
{ | |
throw new Exception("early"); | |
} | |
public static Task<string> GetStringCancelledAsync() | |
{ | |
return Task.FromCanceled<string>(new CancellationToken(true)); | |
} | |
public static Task<string> GetStringCancelledLateAsync() | |
{ | |
return Task.Delay(500) | |
.ContinueWith<Task<string>>(t => Task.FromCanceled<string>(new CancellationToken(true))) | |
.Unwrap(); | |
} | |
public static Task<T> RunAsync<T>(Func<Task<T>> method) | |
{ | |
try | |
{ | |
return method(); | |
} | |
catch (Exception ex) | |
{ | |
return Task.FromException<T>(ex); | |
} | |
} | |
} | |
public static class TaskExtensions | |
{ | |
public static Task<TOutput> Then<TInput, TOutput>( | |
this Task<TInput> task, | |
Func<TInput, TOutput> onSuccess, | |
Func<AggregateException, TOutput> onError = null) | |
{ | |
return task.ContinueWith<TOutput>(t => { | |
try | |
{ | |
return onSuccess(t.Result); | |
} | |
catch (AggregateException aex) | |
{ | |
if (onError == null) | |
{ | |
throw aex.Flatten(); | |
} | |
return onError(aex.Flatten()); | |
} | |
}); | |
} | |
public static Task Then<TInput>( | |
this Task<TInput> task, | |
Action<TInput> onSuccess, | |
Action<AggregateException> onError = null) | |
{ | |
return task.ContinueWith(t => { | |
try | |
{ | |
onSuccess(t.Result); | |
} | |
catch (AggregateException aex) | |
{ | |
if (onError == null) | |
{ | |
throw aex.Flatten(); | |
} | |
onError(aex.Flatten()); | |
} | |
}); | |
} | |
public static Task<T> Catch<TInput, T>( | |
this Task<T> task, | |
Func<AggregateException, T> onError = null) | |
{ | |
return task.ContinueWith<T>(t => { | |
if (t.IsCanceled || t.IsFaulted || !t.IsCompletedSuccessfully) | |
{ | |
var aex = (t.Exception ?? new AggregateException("unknown")).Flatten(); | |
if (onError == null) | |
{ | |
throw aex.Flatten(); | |
} | |
return onError(aex.Flatten()); | |
} | |
return t.Result; | |
}); | |
} | |
public static Task Catch( | |
this Task task, | |
Action<AggregateException> onError) | |
{ | |
return task.ContinueWith(t => { | |
if (t.IsCanceled || t.IsFaulted || !t.IsCompletedSuccessfully) | |
{ | |
var aex = (t.Exception ?? new AggregateException("unknown")).Flatten(); | |
if (onError == null) | |
{ | |
throw aex.Flatten(); | |
} | |
onError(aex.Flatten()); | |
} | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment