[英]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.