c# - 重试机制捕获异常将不起作用
问题描述
如果发生规定的业务逻辑,我正在为 API 调用实现重试机制以发出相同的请求。我现在让它变得非常简单,稍后会通过异常类型处理等来增强它。如果逻辑发生,我只需抛出异常并在重试机制中捕获它们,但在下面的代码只是杀死线程并且在第一次尝试后不执行. 你能帮我请我在这里缺少什么吗?
这是我尝试使用的重试逻辑。
public static T Do<T>(Func<T> action, TimeSpan retryInterval, int attemptCount)
{
var exceptions = new List<Exception>();
for (int attempted = 0; attempted < attemptCount; attempted++)
{
try
{
if (attempted > 0)
{
Thread.Sleep(retryInterval);
}
return action();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
throw new AggregateException(exceptions);
}
这就是我调用重试方法的方式。
await Task.Run(() =>
{
RetryHelper.Do(() => ConfirmRequestRetryAsync(request, true), TimeSpan.FromSeconds(60), 10);
});
这是由于逻辑而可能引发异常的方法。
public async void ConfirmRequestRetryAsync(ConfirmRequest request, bool flag)
{
logger.Info($"Confirm Request Async Called for the request : {JsonConvert.SerializeObject(request)}");
var confirmRequest = GetSignedConfirmRequest(request.PaymentId);
var confirmResponse = await MakeRequest(confirmRequest);
//Added flag and sending at false at first try to not throw exception
//Then in retry mechanism this exceptions will be use to trigger retry logic.
if (flag)
{
var statu = ConfirmResponseXmlConvert(confirmResponse);
if (statu.Item1 == "0" && statu.Item2 == "InProcess")
{
throw new Exception("InProcess");
}
else if (statu.Item1 == "-1" && statu.Item2 != "Declined")
{
throw new Exception("Error");
}
}
}
解决方案
这ConfirmRequestRetryAsync
是一个异步 void 方法。这意味着它将在第一次等待时返回。其余代码将在稍后运行,在与调用者相同的线程上下文中。因此,当抛出异常时,重试方法已经返回,并且没有任何东西可以捕获异常。
修复方法是使其成为异步任务方法,并在您的重试方法中等待它。这可能需要重试方法的两种变体,一种用于异步方法,一种用于非异步。
async void 的经验法则是永远不允许从它们中抛出异常,因为任何人都不可能捕获它们。如果可能出现异常,请始终使用异步任务。
推荐阅读
- php - 通过引用取消设置会话不起作用
- python - 虽然循环不能很好地适应时间
- amazon-web-services - ecs.amazonaws.com 和 ecs-tasks.amazonaws.com 有什么区别?
- sapui5 - 如何在没有数据绑定的情况下使用 sapui5 SmartField?
- javascript - 两个javascript参数如何传递“this”
- arrays - mongodb 匹配数组中的项目作为聚合管道的一部分
- javascript - Weglot 链接挂钩不起作用(在粘性标题上)
- vue.js - Vue 数据、计算和方法
- c - 将指向多维数组的指针作为参数传递
- symfony - Symfony 4. 如何将 DateType 扩展为 HiddenType