Skip to content

Instantly share code, notes, and snippets.

@rgueldenpfennig
Created March 27, 2023 16:30
Show Gist options
  • Select an option

  • Save rgueldenpfennig/346003d9e3cd8349bcf90525b6d25b74 to your computer and use it in GitHub Desktop.

Select an option

Save rgueldenpfennig/346003d9e3cd8349bcf90525b6d25b74 to your computer and use it in GitHub Desktop.
Various Task extension methods
public static class TaskExtensions
{
/// <summary>
/// The given task will be retried a given number of times. In case of failure a delay is introduced before executing the retry.
/// </summary>
public static async Task<T> Retry<T>(
this Func<Task<T>> taskFactory,
int maxRetries,
TimeSpan delay)
{
for (var i = 1; i <= maxRetries; i++)
{
try
{
return await taskFactory();
}
catch
{
if (i == maxRetries)
throw;
await Task.Delay(delay);
}
}
throw new InvalidOperationException();
}
/// <summary>
/// Throws a <see cref="TimeoutException"/> when the given tasks takes longer than the specified time span.
/// </summary>
public static async Task<T> Timeout<T>(this Task<T> task, TimeSpan timeSpan, CancellationToken cancellationToken)
{
var timeoutTask = Task.Delay(timeSpan, cancellationToken);
var completedTask = await Task.WhenAny(task, timeoutTask);
if (completedTask == timeoutTask)
{
throw new TimeoutException();
}
return task.Result;
}
/// <summary>
/// Executes an error handler in case the task encounters an exception.
/// </summary>
public static async Task OnFailure(this Task task, Action<Exception> errorHandler)
{
try
{
await task;
}
catch (Exception ex)
{
errorHandler?.Invoke(ex);
}
}
/// <summary>
/// Fire and forget a task with an optional error handler.
/// </summary>
public static void FireAndForget(this Task task, Action<Exception>? errorHandler = null)
{
task.ContinueWith(t =>
{
if (t.Exception != null && errorHandler != null)
{
errorHandler(t.Exception);
}
}, TaskContinuationOptions.OnlyOnFaulted);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment