我正在尝试使用polly的超时策略。
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
timeoutPolicy().GetAwaiter().GetResult();
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
Console.ReadKey();
}
static async Task timeoutPolicy()
{
AsyncTimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(), CancellationToken.None);
}
static Task<HttpResponseMessage> LongOperation()
{
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
Thread.Sleep(5000); // Sleep 5 seconds
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest
};
});
}
我希望在 1 秒后引发异常,因为这是我设置的超时上限。但目前,不会抛出异常,方法 LongOperation() 在大约 5 秒后正常返回。
为什么在这种情况下超时策略不起作用?
为什么在这种情况下超时策略不起作用?
波莉的TimeoutPolicy
以两种模式存在:
TimeoutStrategy.Optimistic
希望受治理的代表对CancelToken的合作取消做出回应。TimeoutStrategy.Pessimistic
允许调用代码不再等待不响应合作取消的代理。
乐观模式是默认模式,因此您发布的代码使用此模式。但是(a)张贴的代码中的LongOperation()
没有回应合作取消;因此,该策略不会超时。
具有异步策略的悲观模式旨在仅用于管理符合正常异步模式的委托。 发布LongOperation()
中的Thread.Sleep()
是完全同步的;因此,您的示例不会仅通过切换到TimeoutStrategy.Pessimistic
来超时。
TimeoutStrategy.Optimistic
是通过HttpClient
调用的最佳模拟,因为这些调用确实响应CancellationToken
。
异步超时策略的乐观模式超时长操作可以通过await Task.Delay(...)
遵守CancellationToken
来模拟,如下所示:
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Polly;
using Polly.Timeout;
public class Program
{
public static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
try {
timeoutPolicy().GetAwaiter().GetResult();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
stopwatch.Stop();
Console.WriteLine("Time elapsed: {0}", stopwatch.Elapsed);
}
static async Task timeoutPolicy()
{
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(ct), CancellationToken.None);
}
static async Task<HttpResponseMessage> LongOperation(CancellationToken token)
{
await Task.Delay(5000, token);
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest
};
}
}
现在你正在使用超时Optimistic
它期望你调用的delgate尊重并响应取消令牌。您的委托不会,在这种情况下,您需要使用超时Pessimistic
以确保调用方不会等待通过定义的超时。
static async Task timeoutPolicy()
{
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1, TimeoutStrategy.Pessimistic); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(), CancellationToken.None);
}
文档中所述的Polly 超时Optimistic
是默认值。
正如@moutain旅行者已经指出的那样,乐观的超时要求您通过并配合超时取消。这已经通过使用HttpClient
的 api 调用来处理,但在此示例案例中,您的代码将如下所示:
static async Task timeoutPolicy()
{
var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(1, TimeoutStrategy.Optimistic); // setup the timeout limit to be 1 sec
HttpResponseMessage response = await timeoutPolicy.ExecuteAsync((ct) => LongOperation(ct), CancellationToken.None);
}
static Task<HttpResponseMessage> LongOperation(CancellationToken token)
{
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
var longTask = Task.Delay(5000);
while (!longTask.IsCompleted)
{
token.ThrowIfCancellationRequested();
}
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.BadRequest
};
});
}