C# Polly强制超时后任务仍在运行

C# Polly强制超时后任务仍在运行,c#,.net-core,dotnet-httpclient,polly,refit,C#,.net Core,Dotnet Httpclient,Polly,Refit,我正在尝试使用Polly和Refit实现一个重试/超时过程来访问Web服务。 我有一个10秒的超时策略(Polly.timeout.TimeoutRejectedException on timeout)。 我有两次重试的重试策略。 我有一个用户可以取消的userCancellationToken。 如果我没有设置Polly timeout策略,客户端将在100秒后使用System.IO.IOException 虽然这段代码基本上是有效的,但我有一些问题: 1) 我的代码基本正确吗 2) 如果我

我正在尝试使用Polly和Refit实现一个重试/超时过程来访问Web服务。 我有一个10秒的超时策略
(Polly.timeout.TimeoutRejectedException on timeout)
。 我有两次重试的重试策略。 我有一个用户可以取消的
userCancellationToken
。 如果我没有设置Polly timeout策略,客户端将在100秒后使用
System.IO.IOException

虽然这段代码基本上是有效的,但我有一些问题:

1) 我的代码基本正确吗

2) 如果我的超时时间为10秒,并且我强制服务器在15秒后应答,作为超时测试,此代码每次正确尝试3次10秒,然后失败,但几秒钟后我显示3“Success after…”,这意味着任务仍在运行并等待数据,即使Polly取消了它。如何取消正在运行的任务

3) 如果无法访问我的服务器,我会在4秒钟后收到一个
System.Net.Sockets.SocketException
。如何减少此超时

        var timeOutPolicy = Policy
            .TimeoutAsync(
                10,
                TimeoutStrategy.Pessimistic);

        var retryPolicy = Policy
          .Handle<Exception>()              
          .RetryAsync(2, (exception, attempt) =>
          {                  
              sw.Stop();
              progress.Report($"Error after {sw.Elapsed}");
              progress.Report($"New attempt {attempt}");

              if (exception.InnerException is System.Net.Sockets.SocketException)
              {
                  progress.Report("Catched: SocketException (No server running or not reachable)");                      
              }
              if (exception.InnerException is System.IO.IOException)
              {
                  progress.Report("Catched: IOException (normal timeout)");                      
              }
              if (exception is Polly.Timeout.TimeoutRejectedException)
              {
                  progress.Report("Catched: Polly Exception (timeout set by Polly)");
              }                  
              if (exception.InnerException is ApiException) progress.Report("Catched: ApiException");
          });

        var policyWrap = Policy.WrapAsync(retryPolicy, timeOutPolicy);

        try
        {
            await policyWrap.ExecuteAsync(async (ct) =>
            {
                sw.Restart();                    

                progress.Report("Execute");                    

                var api = RestService.For<ICTServerApi>("http://localhost:3105/json/reply/ReqUtenti");

                respUtenti = await api.GetUtentiAsync(reqUtenti, userCancellationToken).ConfigureAwait(false);

                sw.Stop();
                progress.Report($"Success after {sw.Elapsed}");
            }, userCancellationToken).ConfigureAwait(false);
        }            
var timeOutPolicy=策略
.TimeoutAsync(
10,
时间策略(悲观的);
var retryPolicy=Policy
.Handle()
.RetryAsync(2,(异常,尝试)=>
{                  
sw.Stop();
进度报告($“在{sw.appeased}之后出错”);
进度报告($“新尝试{尝试}”);
if(exception.InnerException是System.Net.Sockets.SocketException)
{
报告(“捕获:SocketException(没有服务器运行或无法访问)”;
}
if(exception.InnerException是System.IO.IOException)
{
进度报告(“捕获:IOException(正常超时)”;
}
if(异常为Polly.Timeout.TimeoutRejectedException)
{
progress.Report(“捕获:Polly异常(Polly设置的超时)”;
}                  
if(exception.InnerException是ApiException)progress.Report(“Catched:ApiException”);
});
var policyWrap=Policy.WrapAsync(retryPolicy,timeOutPolicy);
尝试
{
等待policyWrap.ExecuteAsync(异步(ct)=>
{
sw.Restart();
进度报告(“执行”);
var api=RestService.For(“http://localhost:3105/json/reply/ReqUtenti");
respunteti=await api.GetUtentiAsync(requenti,userCancellationToken).ConfigureAwait(false);
sw.Stop();
进度报告($“经过{sw.passed}后成功”);
},userCancellationToken)。配置等待(false);
}            

谢谢

关于第2点:您从不使用
ct
。。也许您应该将它与userCT结合起来,并传递给
GetUtentiAsync
我尝试了等待api。GetUtentiAsync(Requenti,ct)也一样,但行为不会改变
TimeoutStrategy。悲观的
是为不尊重
取消令牌的代理设计的。如果重新装配生成的api接受取消,请切换到
TimeoutStrategy.Optimistic
。谢谢,我切换到乐观,并在改装呼叫中使用了ct,它也取消了任务。关于第2点:您从不使用
ct
。。也许您应该将它与userCT结合起来,并传递给
GetUtentiAsync
我尝试了等待api。GetUtentiAsync(Requenti,ct)也一样,但行为不会改变
TimeoutStrategy。悲观的
是为不尊重
取消令牌的代理设计的。如果重新装配生成的api接受取消,请切换到
TimeoutStrategy.Optimistic
。谢谢,我切换到乐观并在改装呼叫中使用ct,它也取消了任务。