如何解决在 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 library。它不使用轮询;相反,它uses Register
在超时时立即取消等待。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。