我已将Transient Fault Handling Application Block的ExecuteAsync方法包装在重试类中,如下所示:
public class RetryWrapper
{
public Task IncrementalAsync(Func<Task> action)
{
var retryStrategy = new Incremental(3, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
var retryPolicy = new RetryPolicy<AzureServiceBusDetectionStrategy>(retryStrategy);
retryPolicy.Retrying += (sender, args) =>
{
Console.WriteLine("Retry - Count = {0}, Delay = {1}, Exception = {2}",
args.CurrentRetryCount, args.Delay, args.LastException.Message);
};
return retryPolicy.ExecuteAsync(action);
}
}
从我的客户端函数中,我调用它如下:
RetryWrapper retry = new RetryWrapper();
try
{
retry.IncrementalAsync<bool>(this.SomeFunction);
}
catch (Exception ex)
{
Console.WriteLine("All retries failed. Exception details: {0}", ex.ToString());
}
SomeFunction的定义是:
public async Task<bool> SomeFunction()
{
await Task.Delay(100);
throw new Exception("Incremental execute task generic");
}
当我运行程序时,它会重试三次,但在最后一次尝试时,不会像ExecuteAction方法那样抛出异常:
Retry - Count = 1, Delay = 00:00:01, Exception = Incremental execute task generic
Retry - Count = 2, Delay = 00:00:03, Exception = Incremental execute task generic
Retry - Count = 3, Delay = 00:00:05, Exception = Incremental execute task generic
如何从ExecuteAync方法重试后捕获异常?另外,使用这样的包装类是否很好?目的是将瞬态块代码集中在一个地方,所以明天我可以切换库。请建议是否有更好的模式。
答案 0 :(得分:0)
由于异常作为Retrying事件处理程序的事件参数的一部分可用,我猜测重试策略本身正在捕获异常。您可能无法直接在try catch中获取异常,因为策略的内部工作不会重新抛出异常。
但是,您可以为RetryWrapper
课程添加一些支持属性。
public class RetryWrapper
{
private const Int32 RetryTimes = 3;
// Can be private if you don't need all available to caller.
public IList<Exception> Exceptions { get; private set; }
public Exception LastException => Exceptions.LastOrDefault() ?? null;
public Boolean Failed => Exceptions.Count == _retryTimes;
public RetryWrapper() {
Exceptions = new List<Exception>();
}
public Task IncrementalAsync(Func<Task> action)
{
var retryStrategy = new Incremental(RetryTimes, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
var retryPolicy = new RetryPolicy<AzureServiceBusDetectionStrategy>(retryStrategy);
retryPolicy.Retrying += (sender, args) =>
{
Console.WriteLine("Retry - Count = {0}, Delay = {1}, Exception = {2}",
args.CurrentRetryCount, args.Delay, args.LastException.Message);
Exceptions.Add(args.LastException);
};
return retryPolicy.ExecuteAsync(action);
}
}
然后
RetryWrapper retry = new RetryWrapper();
retry.IncrementalAsync<bool>(this.SomeFunction);
if (retry.Failed)
{
Console.WriteLine("All retries failed. Exception details: {0}", retry.LastException.Message.ToString());
}