Skip to content

Instantly share code, notes, and snippets.

@labaneilers
Created October 28, 2017 20:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save labaneilers/7b4ebc79c290c3e8f433010de5697397 to your computer and use it in GitHub Desktop.
Save labaneilers/7b4ebc79c290c3e8f433010de5697397 to your computer and use it in GitHub Desktop.
Promises-link syntax for Tasks in dotnet
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