Skip to content

Instantly share code, notes, and snippets.

@RyuaNerin
Created February 19, 2019 07:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RyuaNerin/677effde0a265cbaee2ced00e26d3144 to your computer and use it in GitHub Desktop.
Save RyuaNerin/677effde0a265cbaee2ced00e26d3144 to your computer and use it in GitHub Desktop.
using System;
using System.Linq;
using System.Threading.Tasks;
namespace TaskExtension
{
internal static class TaskHelper
{
private struct VoidResult
{
}
public static void Finally(this Task task, Action action)
{
task.ContinueWith(eTask =>
{
action();
});
}
public static Task OnSuccess (this Task task, Action action)
{
var tcs = new TaskCompletionSource<VoidResult>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.SetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
action();
});
return tcs.Task;
}
public static Task OnSuccess<TTask> (this Task<TTask> task, Action<TTask> action)
{
var tcs = new TaskCompletionSource<TTask>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.SetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
action(eTask.Result);
});
return tcs.Task;
}
public static Task OnFaulted (this Task task, Action<Exception> exceptionAction)
{
var tcs = new TaskCompletionSource<VoidResult>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
{
var innerException = eTask.Exception.Flatten().InnerExceptions.FirstOrDefault();
exceptionAction?.Invoke(innerException ?? eTask.Exception);
}
else if (eTask.IsCanceled)
tcs.SetCanceled();
else
tcs.TrySetResult(default(VoidResult));
});
return tcs.Task;
}
public static Task<TTask> OnFaulted<TTask> (this Task<TTask> task, Action<Exception> exceptionAction)
{
var tcs = new TaskCompletionSource<TTask>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
{
var innerException = eTask.Exception.Flatten().InnerExceptions.FirstOrDefault();
exceptionAction?.Invoke(innerException ?? eTask.Exception);
}
else if (eTask.IsCanceled)
tcs.SetCanceled();
else
tcs.TrySetResult(eTask.Result);
});
return tcs.Task;
}
public static Task OnCanceled (this Task task, Action action)
{
var tcs = new TaskCompletionSource<VoidResult>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.SetException(eTask.Exception);
else if (eTask.IsCanceled)
action();
else
tcs.SetResult(default(VoidResult));
});
return tcs.Task;
}
public static Task<TTask> OnCanceled<TTask> (this Task<TTask> task, Action action)
{
var tcs = new TaskCompletionSource<TTask>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.SetException(eTask.Exception);
else if (eTask.IsCanceled)
action();
else
tcs.SetResult(eTask.Result);
});
return tcs.Task;
}
public static Task Then (this Task task, Action<Task > next)
{
var tcs = new TaskCompletionSource<VoidResult>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
next(eTask);
tcs.TrySetResult(default(VoidResult));
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
public static Task Then (this Task task, Func <Task, Task > next)
{
var tcs = new TaskCompletionSource<VoidResult>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
next(eTask).ContinueWith(nTask =>
{
if (nTask.IsFaulted)
tcs.TrySetException(nTask.Exception);
else if (nTask.IsCanceled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(default(VoidResult));
});
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
public static Task Then<TTask> (this Task<TTask> task, Action<Task<TTask> > next)
{
var tcs = new TaskCompletionSource<VoidResult>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
next(eTask);
tcs.TrySetResult(default(VoidResult));
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
public static Task Then<TTask> (this Task<TTask> task, Func <Task<TTask>, Task > next)
{
var tcs = new TaskCompletionSource<VoidResult>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
next(eTask).ContinueWith(nTask =>
{
if (nTask.IsFaulted)
tcs.TrySetException(nTask.Exception);
else if (nTask.IsCanceled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(default(VoidResult));
});
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
public static Task<TFunc> Then<TFunc> (this Task task, Func <Task, TFunc > next)
{
var tcs = new TaskCompletionSource<TFunc>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
tcs.TrySetResult(next(eTask));
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
public static Task<TFunc> Then<TFunc> (this Task task, Func <Task , Task<TFunc>> next)
{
var tcs = new TaskCompletionSource<TFunc>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
next(eTask).ContinueWith(nTask =>
{
if (nTask.IsFaulted)
tcs.TrySetException(nTask.Exception);
else if (nTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
tcs.TrySetResult(nTask.Result);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
public static Task<TFunc> Then<TTask, TFunc> (this Task<TTask> task, Func <Task<TTask>, TFunc > next)
{
var tcs = new TaskCompletionSource<TFunc>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
tcs.TrySetResult(next(eTask));
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
public static Task<TFunc> Then<TTask, TFunc> (this Task<TTask> task, Func <Task<TTask>, Task<TFunc>> next)
{
var tcs = new TaskCompletionSource<TFunc>();
task.ContinueWith(eTask =>
{
if (eTask.IsFaulted)
tcs.TrySetException(eTask.Exception);
else if (eTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
next(eTask).ContinueWith(nTask =>
{
if (nTask.IsFaulted)
tcs.TrySetException(nTask.Exception);
else if (nTask.IsCanceled)
tcs.TrySetCanceled();
else
{
try
{
tcs.TrySetResult(nTask.Result);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
}
});
return tcs.Task;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment