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

我正在尝试取消通过共享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");

                }

            }

        }


守候你守候我
浏览 236回答 1
1回答

幕布斯6054654

好吧,通过 StackOverflow 躲避我自己又一次奏效了。Ctrl+C如果没有通过 取消args.Cancel = true,则终止应用程序,因此它与HttpClient或 的关系绝对为零CancellationToken。修复方法很简单:Console.CancelKeyPress += (sender, args) =>{&nbsp; &nbsp; args.Cancel = true;&nbsp; &nbsp; Console.WriteLine("Stopped by user");&nbsp; &nbsp; cancellationTokenSource.Cancel(true);};
打开App,查看更多内容
随时随地看视频慕课网APP