There are 4 different scenarios based on
- your decorated code is synchronous or asynchronous
- your timeout is using optimistic or pessimistic strategy
Sync Policy + Pessimistic strategy
var syncTimeoutPessimistic = Policy.Timeout(
TimeSpan.FromSeconds(3),
TimeoutStrategy.Pessimistic,
(_, __, ___) =>
{
"onTimeout is fired".Dump();
});
try
{
syncTimeoutPessimistic.Execute(() =>
{
Thread.Sleep(5_000);
"Decorated operation is finished".Dump();
});
}
catch(TimeoutRejectedException)
{
"Timeout has kicked in".Dump();
}
Sync Policy + Optimistic strategy
CancellationToken should be respected otherwise it won't work
var syncTimeoutOptimistic = Policy.Timeout(
TimeSpan.FromSeconds(3),
TimeoutStrategy.Optimistic,
(_, __, ___) =>
{
"onTimeout is fired".Dump();
});
try
{
syncTimeoutOptimistic.Execute((ct) =>
{
var result = Task.Run(() => { Thread.Sleep(5_000); return Task.CompletedTask; });
result.Wait(ct);
"Decorated operation is finished".Dump();
}, CancellationToken.None);
}
catch(TimeoutRejectedException)
{
"Timeout has kicked in".Dump();
}
It is more like a hack than a suggested way.
Async Policy + Pessimistic strategy
var asyncTimeoutPessimistic = Policy.TimeoutAsync(
TimeSpan.FromSeconds(3),
TimeoutStrategy.Pessimistic,
(_, __, ___) =>
{
"onTimeout is fired".Dump();
return Task.CompletedTask;
});
try
{
await asyncTimeoutPessimistic.ExecuteAsync(async () =>
{
await Task.Delay(5_000);
"Decorated operation is finished".Dump();
});
}
catch(TimeoutRejectedException)
{
"Timeout has kicked in".Dump();
}
Async + Optimistic strategy
CancellationToken should be respected otherwise it won't work
var asyncTimeoutOptimistic = Policy.TimeoutAsync(
TimeSpan.FromSeconds(3),
TimeoutStrategy.Optimistic,
(_, __, ___) =>
{
"onTimeout is fired".Dump();
return Task.CompletedTask;
});
try
{
await asyncTimeoutOptimistic.ExecuteAsync(async (ct) =>
{
await Task.Delay(5_000, ct);
"Decorated operation is finished".Dump();
}, CancellationToken.None);
}
catch(TimeoutRejectedException)
{
"Timeout has kicked in".Dump();
}
In all cases you should see the following output:
Dumping object(String)
onTimeout is fired
Dumping object(String)
Timeout has kicked in
So, for your code (async Policy + Pessimistic strategy) you should use a different overload of ExecuteAsync which utilizes the CancellationToken. Don't forget to pass the ct to the Task.Delay!!!
p => p.ExecuteAsync(async ct =>
{
await Task.Delay(TimeSpan.FromSeconds(2) ct);
return new HttpResponseMessage(System.Net.HttpStatusCode.OK);
}, CancellationToken.None)