public static class TaskExtensions
{
///
/// The given task will be retried a given number of times. In case of failure a delay is introduced before executing the retry.
///
public static async Task Retry(
this Func> 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();
}
///
/// Throws a when the given tasks takes longer than the specified time span.
///
public static async Task Timeout(this Task 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;
}
///
/// Executes an error handler in case the task encounters an exception.
///
public static async Task OnFailure(this Task task, Action errorHandler)
{
try
{
await task;
}
catch (Exception ex)
{
errorHandler?.Invoke(ex);
}
}
///
/// Fire and forget a task with an optional error handler.
///
public static void FireAndForget(this Task task, Action? errorHandler = null)
{
task.ContinueWith(t =>
{
if (t.Exception != null && errorHandler != null)
{
errorHandler(t.Exception);
}
}, TaskContinuationOptions.OnlyOnFaulted);
}
}