Fallback.AsyncFallbackEngine Exception



我在.NET Framework 4.8(WCF(中有一个应用程序可以进行http调用,也可以使用Polly进行重试和回退管理,但有时会引发System.NullReferenceException,但我不知道问题出在哪里。这是代码:

private static async Task<bool> CallApi<TRequest>(TRequest request, string requestUri, Func<string, StringContent, Task<HttpResponseMessage>> func)
{
var jsonRequest = JsonConvert.SerializeObject(request);
var fallBackPolicy = Policy<HttpResponseMessage>.Handle<Exception>()
.FallbackAsync(new HttpResponseMessage(HttpStatusCode.SeeOther)
{
Content = new StringContent($"Exception has occurred in migration call. RequestUri: {requestUri}")
}, 
result => 
{
LogEventService.Logger.Error(result.Exception, "An unhandled exception occurred while retrying calling");
return Task.CompletedTask;
});
var waitAndRetryPolicy = Policy.HandleResult<HttpResponseMessage>(res => res.StatusCode == HttpStatusCode.InternalServerError).
WaitAndRetryAsync(2, retryAttempts => TimeSpan.FromMilliseconds(500));
var response = await fallBackPolicy
.WrapAsync(waitAndRetryPolicy)
.ExecuteAsync(async () =>
{
using (var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json"))
{
content.Headers.Add("X-Correlation-ID", HttpContext.Current.Session[RequestId].ToString());
return await func(requestUri, content);
}
});

if(response.IsSuccessStatusCode)
return true;
await LogMessage(LogLevel.Error, response, requestUri);

return false;
}

这是StackTrace

System.NullReferenceException:对象引用未设置为实例对象的
在UserMigrationService<gt;c_DisplayClass22_0'1。<b_3>d.MoveNext((在里面…\Services\UserMigrationService.cs:line 474
---从引发异常的前一位置开始的堆栈跟踪结束---

位于System.Runtime.ExceptionServices.ExceptionDispatchInfo.Sthrow((
atPolly.Retry.AsyncRetryEngine.d_0'1.MoveNext((
---从引发异常的前一位置开始的堆栈跟踪结束---

System.Runtime.ExceptionServices.ExceptionDispatchInfo.Sthrow((处的

System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务(处的
Polly.AncurrentPolicy'1.d_13.MoveNext((
---从引发异常的前一位置开始的堆栈跟踪结束---

System.Runtime.ExceptionServices.ExceptionDispatchInfo.Sthrow((处的

<blockquote\>位于System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务(处的
Polly.Wrapa.AsyncPolicyWrapEngine。<gt;c__DisplayClass0_0'1。<b_ 0>d.MoveNext((
---从引发异常的前一位置开始的堆栈跟踪结束---

在System.Runtime.ExceptionServices.ExceptionDispatchInfo.Sthrow((>在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务(
Polly.Fallback.AsyncFallbackEngine.d_0'1.MoveNext((

你能帮我找出错误的零件在哪里吗?我怎样才能更好地理解为什么抛出此异常
感谢所有

事实证明,NRE是在这一行抛出的:

ontent.Headers.Add("X-Correlation-ID", HttpContext.Current.Session[RequestId].ToString());

这表明CCD_ 2可能是CCD_。ExecuteAsync接收一个委托,该委托可能与CallApi方法的其余代码不在同一线程上运行。

这就是HttpContext不会流入代理的原因。

修复非常简单:您必须在CallApi中捕获RequestId,而不是在ExecuteAsync委托中捕获:

var correlationId = HttpContext.Current.Session[RequestId].ToString();
var response = await fallBackPolicy
.WrapAsync(waitAndRetryPolicy)
.ExecuteAsync(async () =>
{
using (var content = new StringContent(jsonRequest, Encoding.UTF8, "application/json"))
{
content.Headers.Add("X-Correlation-ID", correlationId);
return await func(requestUri, content);
}
});

我还建议使用Policy.Wrap(参考(,而不是对其中一个策略调用WrapAsync方法。以下两行是等效的:

fallBackPolicy.WrapAsync(waitAndRetryPolicy)
Policy.WrapAsync(fallbackPolicy, waitAndRetryPolicy)

所以,你的代码可以这样重写:

var correlationId = HttpContext.Current.Session[RequestId].ToString();
var strategy = Policy.WrapAsync(fallbackPolicy, waitAndRetryPolicy);
var response = await strategy
.ExecuteAsync(async (ct) =>
{
using (var content = new StringContent(jsonRequest, Encoding.UTF8, MediaTypeNames.Application.Json))
{
content.Headers.Add("X-Correlation-ID", correlationId);
//TODO: pass the cancellationToken to the func
return await func(requestUri, content);
}
}, CancellationToken.None);

我使用了ExecuteAsync的另一个过载,您正在接收CancellationToken。当您考虑使用超时策略时,这可能非常有用。在这种情况下,您应该将该令牌传递给func函数。

相关内容

  • 没有找到相关文章

最新更新