Skip to content

Instantly share code, notes, and snippets.

@CleanCoder
Last active April 8, 2020 09:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save CleanCoder/86b26220c9a0b26ef07a5f41512417d3 to your computer and use it in GitHub Desktop.
Save CleanCoder/86b26220c9a0b26ef07a5f41512417d3 to your computer and use it in GitHub Desktop.
Task Extension
static async Task<T> Otherwise<T> (this Task<T> task, Func<Task<T>> orTask) {
task.ContinueWith (async innerTask => {
if (innerTask.Status == TaskStatus.Faulted)
return await orTask ();
return await Task.FromResult<T> (innerTask.Result);
}).Unwrap ();
}
static async Task<T> Retry<T> (Func<Task<T>> task, int retries, TimeSpan delay, CancellationToken cts = default (CancellationToken)) {
await task ().ContinueWith (async innerTask => {
cts.ThrowIfCancellationRequested ();
if (innerTask.Status != TaskStatus.Faulted)
return innerTask.Result;
if (retries == 0)
throw innerTask.Exception ??
throw new Exception ();
await Task.Delay (delay, cts);
return await Retry (task, retries - 1, delay, cts);
}).Unwrap ();
}
// Example:
Image image = await AsyncEx.Retry (async () =>
await DownloadImageAsync ("Bugghina001.jpg").Otherwise (async () =>await DownloadImageAsync ("Bugghina002.jpg")),
5, TimeSpan.FromSeconds (2));
static Task<T> Catch<T, TError> (this Task<T> task, Func<TError, T> onError) where TError : Exception {
var tcs = new TaskCompletionSource<T> ();
task.ContinueWith (innerTask => {
if (innerTask.IsFaulted && innerTask?.Exception?.InnerException is TError)
tcs.SetResult (onError ((TError) innerTask.Exception.InnerException));
else if (innerTask.IsCanceled)
tcs.SetCanceled ();
else if (innerTask.IsFaulted)
tcs.SetException (innerTask?.Exception?.InnerException ??throw new InvalidOperationException ());
else
tcs.SetResult (innerTask.Result);
});
return tcs.Task;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment