gpt4 book ai didi

c# - 任何区分取消和超时的方法

转载 作者:可可西里 更新时间:2023-11-01 08:43:26 24 4
gpt4 key购买 nike

我有一些代码通过调用许多其他服务来验证某些数据。我并行启动所有调用,然后等到至少其中一个调用完成。如果任何请求失败,我不关心其他调用的结果。

我使用 HttpClient 进行调用,并且我传递了一个 HttpMessageHandler,它会执行大量日志记录。本质上:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = null;

try
{
response = await base.SendAsync(request, cancellationToken);
}
catch (OperationCanceledException ex)
{
LogTimeout(...);
throw;
}
catch (Exception ex)
{
LogFailure(...);
throw;
}
finally
{
LogComplete(...);
}

return response;
}

没有,我遇到麻烦的部分是取消请求。当我取消请求时,我是故意这样做的,所以我不希望它被记录为超时,但取消和真正的超时之间似乎没有任何区别。

有没有办法做到这一点?

编辑:我需要稍微澄清一下。并行调用的服务在超时时传入 CancellationTokens:

var ct = new CancellationTokenSource(TimeSpan.FromSeconds(2));

因此,当服务器响应时间超过两秒时,我得到一个OperationCanceledException,如果我手动取消 token 源(比如因为另一台服务器在 1 秒后返回错误),那么我仍然得到一个 OperationCanceledException。理想情况下,我将能够查看 CancellationToken.IsCancellationRequested 以确定它是否由于超时而被取消,而不是明确请求取消,但无论如何它被取消了。

最佳答案

如果要区分这两种取消类型,则需要使用两种不同的取消标记。没有别的办法。这并不难,因为他们 can be linked - 只是有点尴尬。

编写此 IMO 最干净的方法是将超时代码移到 SendAsync 方法而不是调用方法中:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
cts.CancelAfter(TimeSpan.FromSeconds(2));
try
{
return await base.SendAsync(request, cts.Token);
}
catch (OperationCanceledException ex)
{
if (cancellationToken.IsCancellationRequested)
return null;
LogTimeout(...);
throw;
}
catch (Exception ex)
{
LogFailure(...);
throw;
}
finally
{
LogComplete(...);
}
}
}

如果您不想将超时代码移动到 SendAsync 中,那么您也需要在该方法之外进行日志记录。

关于c# - 任何区分取消和超时的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35615638/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com