[英]Generic async Retry with Timeout function in C#
我有幾百個調用各種外部API,我希望將其包裝在一個能夠重試和處理超時的通用異步函數中。
基本上,我認為我需要實現類似這個函數調用的東西:
await Retry(()=>someFunctionAsync(doWorkParams, new CancellationToken()), retryCount, timeout);
如何定義此類重試功能? 另外,我如何從同步代碼中調用此功能,因為我的調用大量存在於同步方法中?
如何定義此類重試功能?
Polly
。 這樣的事情應該有效:
static async Task RetryAsync(Func<CancellationToken, Task> func, int retryCount, TimeSpan timeout)
{
using (var cts = new CancellationTokenSource(timeout))
{
var policy = Policy.Handle<Exception>(ex => !(ex is OperationCanceledException))
.RetryAsync(retryCount);
await policy.ExecuteAsync(() => func(cts.Token)).ConfigureAwait(false);
}
}
另外,我如何從同步代碼中調用此功能,因為我的調用大量存在於同步方法中?
這是一個完全不同的問題。 阻止異步代碼總是有陷阱。 沒有適用於任何Func<Task>
解決方案。 如果您必須這樣做,請參閱我的MSDN文章,了解您可以嘗試的各種黑客攻擊。 但是,保持異步代碼異步和同步代碼同步會更好。
如果你仍然對如何在沒有政策的情況下這樣做感到好奇,那將是這樣的:
/// Untested code
static class Retry
{
public static async Task<T> Run<T>(Func<CancellationToken, Task<T>> function, int retries, TimeSpan timeout)
{
Exception error = null;
do
{
try
{
var cancellation = new CancellationTokenSource(timeout);
return await function(cancellation.Token).ConfigureAwait(false);
}
catch (Exception ex)
{
error = ex;
}
retries--;
}
while (retries > 0);
throw error;
}
public static async Task<T> Run<T>(Func<Task<T>> function, int retries, TimeSpan timeout)
{
Exception error = null;
do
{
try
{
var timeoutTask = Task.Delay(timeout);
var resultTask = function();
await Task.WhenAny(resultTask, timeoutTask).ConfigureAwait(false);
if (resultTask.Status == TaskStatus.RanToCompletion)
return resultTask.Result;
else
error = new TimeoutException();
}
catch (Exception ex)
{
error = ex;
}
retries--;
}
while (retries > 0);
throw error;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.