c# - 如何使用 polly 启用超时策略
问题描述
我正在尝试使用 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 秒后正常返回。
为什么超时策略在这种情况下不起作用?
解决方案
为什么超时策略在这种情况下不起作用?
PollyTimeoutPolicy
有两种模式:
TimeoutStrategy.Optimistic
期望受治理的代表通过 CancellationToken 响应合作取消。TimeoutStrategy.Pessimistic
允许调用代码离开等待不响应合作取消的委托。
乐观模式是默认模式,因此您发布的代码使用此模式。但 (a)LongOperation()
在贴出的代码中不响应合作取消;所以策略不会超时。
带有异步策略的悲观模式被有意设计为仅用于管理符合正常异步模式的委托。Thread.Sleep()
在张贴LongOperation()
中是完全同步的;因此,您的示例也不会仅通过切换到TimeoutStrategy.Pessimistic
.
TimeoutStrategy.Optimistic
是呼叫通过的最佳模拟HttpClient
,因为那些呼叫确实响应CancellationToken
。
await Task.Delay(...)
可以通过尊重 a来模拟异步超时策略的乐观模式超时操作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
};
}
}
推荐阅读
- ruby-on-rails - Join tables in ActiveRecord Migrations
- python - Python - 根据函数参数构造变量名
- configuration - 如何在电子邮件正文 Outlook 中生成收件人姓名?
- node.js - 在 RHEL 服务器上安装特定版本的 nodejs
- javascript - Angularjs预先输入名称未定义
- c++ - 如何在 OpenCV c++ 中压缩 TIFF 格式的图像?
- php - 使用 substr 作为 Laravel 控制器上的数据库列之一
- python - 骰子游戏 // 到达 GAME_END_POINTS 时循环未正确退出
- c# - 绝对透明窗
- java - Intellij 无法找到依赖模块中所做的更改