在 CancellationTokenSource 上使用 CancelAfter 和循环
Posted
技术标签:
【中文标题】在 CancellationTokenSource 上使用 CancelAfter 和循环【英文标题】:Use CancelAfter on CancellationTokenSource with loop 【发布时间】:2021-06-17 13:05:33 【问题描述】:我想创建一个实现超时的类助手。 因为任务一旦启动就无法停止,我使用循环。 我想在不通过 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 pageurl");
HttpClient httpclient = new HttpClient();
return await httpclient.GetAsync(url);//.ConfigureAwait(false);
【问题讨论】:
“我想使用这个模式而不在 GetAsync 上传递 CancellationToken。” 请问为什么? GetAsync 是一个使用示例,我的意图是使用一个执行时间最长的辅助任务 什么辅助任务?您将如何实现最大执行时间?请尽量完整地回答您的问题,以便我们为您提供最好的帮助 【参考方案1】:我想在 GetAsync 上不通过 CancellationToken 使用此模式。
请记住,取消是合作的,所以这最终只会取消 wait 而不是操作本身。
它是您可以使用的最好的还是循环会导致性能问题?
完全正确的解决方案相当棘手,因为很容易忘记在正确的时间处理所有内容。我建议使用我的AsyncEx library 中的TaskExtensions.WaitAsync(CancellationToken)
。它不使用轮询;相反,它uses Register
在超时时立即取消等待。
【讨论】:
以上是关于在 CancellationTokenSource 上使用 CancelAfter 和循环的主要内容,如果未能解决你的问题,请参考以下文章
对 CancellationTokenSource.Cancel 的调用永远不会返回
在 CancellationTokenSource 上使用 CancelAfter 和循环
异步与并行~CancellationTokenSource对线程的作用
在取消和处理 CancellationTokenSource 之间存在延迟是不是可以保证 IsCancellationRequested 将设置为 true?