c# - 在 CancellationTokenSource 上使用 CancelAfter 和循环
问题描述
我想创建一个实现超时的类助手。因为任务一旦启动就无法停止,我使用循环。我想在不通过 GetAsync 的 CancellationToken 的情况下使用此模式。我的问题是:这个代码是你可以使用的最好的,还是循环会导致性能问题?要了解示例:如果您更改https://reqres.in/api/users?delay=3(延迟=4),您没有超时。如果没有提出 CancelAfter 的另一个重要问题,为什么我的代码仍然可以运行(见输出)?
using System;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
namespace RetryDemo {
class Program {
static void Main(string[] args) {
Example();
Console.ReadLine();
}
private static void Example() {
Stopwatch Stopwatch = Stopwatch.StartNew();
try {
AppDomain.CurrentDomain.UnhandledException += (sender, e) => { Console.WriteLine(((AggregateException)e.ExceptionObject).InnerExceptions.Single().Message); };
var source = new CancellationTokenSource();
var token = source.Token;
var task = Task.Run(async () => {
try {
using (token.Register(() => {
Console.WriteLine($"Timeout elapsed {Stopwatch.Elapsed}");
})) {
Task<HttpResponseMessage> message = GetPage("https://reqres.in/api/users?delay=4");
while (true) {
if (!token.IsCancellationRequested) {
if (message.IsCompleted) {
HttpResponseMessage messageSync = await message;
Console.WriteLine(await messageSync.Content.ReadAsStringAsync());
}
} else {
break;
}
Thread.Sleep(200);
Console.Write(".");
}
}
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
});
source.CancelAfter(3500);
} catch (Exception ex) {
Console.Write(ex.Message);
}
}
public static async Task<HttpResponseMessage> GetPage(string url) {
Console.WriteLine($"Calling page{url}");
HttpClient httpclient = new HttpClient();
return await httpclient.GetAsync(url);//.ConfigureAwait(false);
}
}
}
解决方案
我想在不通过 GetAsync 的 CancellationToken 的情况下使用此模式。
请记住,取消是合作的,所以这最终只会取消等待而不是操作本身。
它是您可以使用的最好的还是循环会导致性能问题?
一个完全正确的解决方案相当棘手,因为很容易忘记在正确的时间处理所有东西。我建议TaskExtensions.WaitAsync(CancellationToken)
从我的AsyncEx 库中使用。它不使用轮询;相反,它用于Register
在超时时立即取消等待。
推荐阅读
- apache-spark - Py4JJavaError:调用 o57.sql 时发生错误。:org.apache.spark.SparkException:作业中止
- php - 使用 ajax 和 jquery 对 sql 行进行即时复选框更新
- flutter - Flutter 如何使用 BottomNavigationBar 管理单独的导航堆栈?
- android - 将文件写入外部存储,以便用户可以从文件存储访问
- php - 是否有 PHPDoc 标准来描述通过引用传递的函数属性?
- ios - Xcode 11.5 不支持 iOS 13.6?
- amazon-web-services - 我需要使用 cloudfront 和 s3 重定向我的 url
- javascript - Ajax 调用在 Visual Studio 代码中不起作用(2020 年 6 月)
- powershell - 如何使用 Powershell 在 Edge Chromium 中设置主页?
- angular - 如何生成 FormArray 项?