繁体   English   中英

带有取消令牌的 Polly 不适用于同步线程

[英]Polly with cancellation token is not working for synchronous thread

我是 Polly 的新手,所以与我尝试做的方法相比,可能有一种完全不同的方法,那完全没问题。 我的目标是:

  1. 我正在使用超时策略: TimeoutStrategy.Optimistic
  2. 我想超时给定clientTimeOut的调用
  3. 我正在使用取消令牌使线程超时

我正在使用取消令牌使调用超时,但不知何故,下面的代码不起作用。 我没有在添加取消令牌时创建新线程,而是使用相同的线程来遵守超时。 它是否总是需要在异步调用中添加取消令牌,即ExecuteAsync()或使用另一个线程? 有人可以帮我解决以下代码有什么问题以及为什么超时不起作用吗?

注意:使用TimeoutStrategy.Pessimist对我有用,但由于其他一些用例,我不能使用它。 我需要从请求上下文中读取 https 标头,我们将在使用异步调用时丢失此信息。 因此我需要使用同步调用。

public TResult ExecuteWrapper<TResult>(Func<CancellationToken ,TResult> func)
{
    int attempts = 0;
    int retryCounter = 3;
    int waitTime = 1000;
    int clientTimeOut = 10000;
    var cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(10000));
    var cancellationToken = cts.Token;

    RetryPolicy retryPolicy = Policy.Handle<Exception>().Retry(retryCounter);
    retryPolicy = Policy.Handle<Exception>().WaitAndRetry(retryCounter, sleepDurationProvider: attempt => TimeSpan.FromMilliseconds(this.waitTime), onRetry: (exception, timeSpan) =>
    {
          logRetryException(timeSpan, attempts++, exception);
    });
    
    PolicyWrap retrypolicywrap = retryPolicy.Wrap(Policy.Timeout(TimeSpan.FromMilliseconds(clientTimeOut), TimeoutStrategy.Optimistic));
    return retrypolicywrap.Execute(func, cancellationToken);
} 

public void BaseFunction(){
   var result = ExecuteWrapper(() => DummyFunctionToSleepTheThread())
}

public string DummyFunctionToSleepTheThread(){
   //Reading http header from the request context
   //which will lost if we use async call 
   //Hence we can't use Task.Delay(milliseconds) here.
    int milliseconds = 15000;
    System.Threading.Thread.Sleep(milliseconds);
    return "SUCCESS";
}

我尝试添加取消令牌,但它没有遵守超时。

您不能使用乐观超时策略来取消Thread 该策略使用CancellationToken的合作行为。 Thread不像Task那样原生支持CancellationToken

所以,你有两个选择。 退回到悲观超时策略或使用Task而不是Thread

据我从您的代码中可以看出,您还没有设计您的解决方案来利用Task和 async-await。 所以,尽量使用悲观策略。


更新 #1

这是一个简单的应用程序,它展示了不同之处

请注意, 超时的波纹管过载需要而不是毫秒

public static void Main()
{
    var optimisticTimeout = Policy.Timeout(1, TimeoutStrategy.Optimistic);
    optimisticTimeout.Execute(ToBeDecoratedMethod);
    var pessimisticTimeout = Policy.Timeout(1, TimeoutStrategy.Pessimistic);
    try
    {
        pessimisticTimeout.Execute(() => ToBeDecoratedMethod());
    }
    catch(TimeoutRejectedException)
    {
        Console.WriteLine("Timed out");
    }
}

public static void ToBeDecoratedMethod()
{
    Console.WriteLine("Before Sleep");
    Thread.Sleep(1_500);
    Console.WriteLine("After Sleep");
}

output 将是:

Before Sleep
After Sleep
Before Sleep
Timed out

可以在这个 do.net fiddle link上找到工作代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM