🖥 5 полезных методов расширения для Task.



1. Запустить и забыть



Иногда необходимо начать выполнение задачи без ожидания ее окончания, особенно когда результат не критичен. Будем использовать расширенный метод "FireAndForget". При необходимости, мы можем передать обработчик ошибок в метод, который будет вызываться, если задача выдает исключение.



public static void FireAndForget(

this Task task,

Action<Exception> errorHandler = null)

{

task.ContinueWith(t =>

{

if (t.IsFaulted && errorHandler != null)

errorHandler(t.Exception);

},

TaskContinuationOptions.OnlyOnFaulted);

}


Использование:

SendEmailAsync().FireAndForget(

e => Console.WriteLine(e.Message));




2. Повтор



Для повторного выполнения задачи мы можем создать метод Retry, который позволит нам установить максимальное количество попыток и задержку между ними. Он будет работать до выполнения задачи или достижения максимальной попытки.



public static async Task<TResult>

Retry<TResult>(

this Func<Task<TResult>> taskFactory,

int maxRetries,

TimeSpan delay)

{

for (int i = 0; i < maxRetries; i++)

{

try

{

return await taskFactory()

.ConfigureAwait(false);

}

catch

{

if (i == maxRetries - 1)

throw;

await Task.Delay(delay)

.ConfigureAwait(false);

}

}

// не должно достигать этого места

return default(TResult);

}



Использование:

var result = await (

() => GetResultAsync())

.Retry(3, TimeSpan.FromSeconds(1));




3. Действие при сбое



Выполняется в случае возникновения ошибок или исключений при выполнении задачи



public static async Task

OnFailure(this Task task,

Action<Exception> onFailure)

{

try

{

await task.ConfigureAwait(false);

}

catch (Exception ex)

{

onFailure(ex);

}

}



Использование:

await GetResultAsync()

.OnFailure(ex => Console.WriteLine(ex.Message));




4. Установка Тайм-аута



Установка тайм-аута для задачи полезна, когда вы хотите, чтобы задача не выполнялась очень долго.



public static async Task

WithTimeout(this Task task,

TimeSpan timeout)

{

var delayTask = Task.Delay(timeout);

var completedTask = await

Task.WhenAny(task, delayTask)

.ConfigureAwait(false);

if (completedTask == delayTask)

throw new TimeoutException();



await task;

}






Использование:

await GetResultAsync()

.WithTimeout(TimeSpan.FromSeconds(1));




5. Результат по умолчанию



Бывают ситуации, когда нужно вернуть результат по умолчанию при сбое задачи:





public static async Task<TResult>

Fallback<TResult>(

this Task<TResult> task,

TResult fallbackValue)

{

try

{

return await task.ConfigureAwait(false);

}

catch

{

return fallbackValue;

}

}



Использование:

var result = await GetResultAsync()

.Fallback("fallback");




Статья



@csharp_ci