I'm new to Polly so there may be a completely different approach compared to the one I'm trying to do and that would be perfectly OK. My goals are this:
- I am using timeout strategy as:
TimeoutStrategy.Optimistic
- I want to timeout the call for given
clientTimeOut
- I am using cancellation token to timeout the thread
I am using cancellation token to timeout the call but somehow the below code is not working. I am not creating a new thread while adding a cancellation token but using the same thread to honoured the timeout.
Does it always need to add the cancellation token in asynchronous call i.e. ExecuteAsync()
or use another thread for it ?
Can someone help me with what is wrong with the below code and why timeout is not working?
Note: Using TimeoutStrategy.Pessimist
will work for me but I can’t use this due to some other usecase. I need to read the https headers from request context, and we will loose this information when using async call. Hence I need to use the sync call.
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";
}
I tried adding the cancellation token but it did not honoured the timeout.
You can't use optimistic timeout strategy to cancel a
Thread
. This strategy uses the co-operative behaviour of theCancellationToken
.Thread
s do not natively supportCancellationToken
likeTask
s.So, you have two options. Fall back to pessimistic timeout strategy or use
Task
instead ofThread
.As far as I can tell from the your code you haven't designed your solution to take advantage of
Task
s and async-await. So, try to use the pessimistic strategy.UPDATE #1
Here is a simple app which demonstrates the difference
(Please note that bellow overload of Timeout requires seconds not milliseconds)
The output will be:
The working code can be found on this dotnet fiddle link.