为了账号安全,请及时绑定邮箱和手机立即绑定

使用 CancellationToken 和 Ctrl+C 取消多个 HttpClient 调用

使用 CancellationToken 和 Ctrl+C 取消多个 HttpClient 调用

C#
守候你守候我 2021-07-07 18:53:48
我正在尝试取消通过共享HttpClient使用发出的多个异步 Web 请求 (GET) CancellationTokens,在命令行应用程序中,完整框架,.net 4.7.1,C# 7.3,VS 2017。我的示例运行了几个并行任务,每个任务都使用异步通过 Http 不断下载一些数据GetAsync(),ReadAsStringAsync()但我使用例如ReadAsByteArrayAsync().终止是通过挂钩Console.CancelKeyPress和取消 my CancellationTokenSource.尽管出于某种原因这看起来很简单,但我无法理解它并想出一个产生可靠结果的解决方案。有时一切都按预期关闭,即所有任务都完成(取消),但更多时候不是关闭只是看似挂起。在没有调试器(有/没有调试)的情况下运行会终止应用程序,但不是以我预期的方式。更少的任务意味着更可能干净地关闭。在处于“挂起”状态时暂停调试中的所有线程似乎表明某些线程卡在其中,GetAsync()但要确切了解发生了什么有点困难。实际上,应用程序如何退出并不重要,但我想了解这一点并能够始终如一地产生干净且受控的关闭,这在我看来使用此构造似乎是可能的,但我很可能错过了一些细节。using System;using System.Linq;using System.Net;using System.Net.Http;using System.Threading;using System.Threading.Tasks;namespace HttpClientAsyncTest{    class Program    {        static async Task<int> Main()        {            using (var cancellationTokenSource = new CancellationTokenSource())            {                Console.CancelKeyPress += (sender, a) =>                {                    Console.WriteLine("Stopped by user");                    cancellationTokenSource.Cancel();                };                var task = RunAsync(cancellationTokenSource);                Console.WriteLine("Running - Press CTRL+C to stop");                await task;            }            Console.WriteLine("All done, exiting");            return 0;        }        private static async Task RunAsync(CancellationTokenSource cts)        {            using (var client = new HttpClient())            {                try                {                    var tasks = Enumerable.Range(1, 10).Select(id => ProcessBatchAsync(client, id, cts.Token));                    await Task.WhenAll(tasks);                }                catch (OperationCanceledException)                {                    Console.WriteLine("Operation cancelled somehow");                }            }        }
查看完整描述

1 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

好吧,通过 StackOverflow 躲避我自己又一次奏效了。


Ctrl+C如果没有通过 取消args.Cancel = true,则终止应用程序,因此它与HttpClient或 的关系绝对为零CancellationToken。


修复方法很简单:


Console.CancelKeyPress += (sender, args) =>

{

    args.Cancel = true;

    Console.WriteLine("Stopped by user");

    cancellationTokenSource.Cancel(true);

};


查看完整回答
反对 回复 2021-07-10
  • 1 回答
  • 0 关注
  • 235 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信