自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

C# 異步編程與列表任務(wù)取消詳解

開發(fā) 前端
在實(shí)際開發(fā)中,我們經(jīng)常需要處理耗時的異步操作,比如網(wǎng)絡(luò)請求、文件讀寫等。有時候,我們可能需要取消這些正在進(jìn)行的異步操作。本文將詳細(xì)介紹如何在C#中實(shí)現(xiàn)異步操作的取消機(jī)制。

在實(shí)際開發(fā)中,我們經(jīng)常需要處理耗時的異步操作,比如網(wǎng)絡(luò)請求、文件讀寫等。有時候,我們可能需要取消這些正在進(jìn)行的異步操作。本文將詳細(xì)介紹如何在C#中實(shí)現(xiàn)異步操作的取消機(jī)制。

前置條件

  • .NET 5.0或更高版本
  • Visual Studio或Visual Studio Code
  • 基本的C#異步編程知識

核心概念

在開始之前,讓我們了解幾個重要的概念:

  1. CancellationTokenSource用于發(fā)出取消信號的源
  2. CancellationToken用于接收取消信號的令牌
  3. Task表示異步操作的對象

完整示例代碼

下面是一個完整的示例,展示如何實(shí)現(xiàn)可取消的異步操作:

using System.Diagnostics;

namespace AppCancellationToken
{
    internal class Program
    {
        // 創(chuàng)建取消令牌源
        static readonly CancellationTokenSource s_cts = new CancellationTokenSource();

        // 創(chuàng)建HttpClient實(shí)例
        static readonly HttpClient s_client = new HttpClient
        {
            MaxResponseContentBufferSize = 1_000_000
        };

        // 待下載的URL列表
        static readonly IEnumerable<string> s_urlList = newstring[]
        {
        "https://learn.microsoft.com",
        "https://learn.microsoft.com/dotnet",
        "https://learn.microsoft.com/azure",
        "https://learn.microsoft.com/visualstudio"
        };

        static async Task Main()
        {
            Console.WriteLine("程序啟動...");
            Console.WriteLine("按回車鍵取消下載...\n");

            // 創(chuàng)建監(jiān)聽取消的任務(wù)
            Task cancelTask = Task.Run(() =>
            {
                while (Console.ReadKey().Key != ConsoleKey.Enter)
                {
                    Console.WriteLine("按回車鍵取消下載...");
                }
                Console.WriteLine("\n檢測到回車鍵:正在取消下載...\n");
                s_cts.Cancel();
            });

            // 創(chuàng)建下載任務(wù)
            Task sumPageSizesTask = SumPageSizesAsync();

            // 等待任意一個任務(wù)完成
            Task finishedTask = await Task.WhenAny(cancelTask, sumPageSizesTask);

            if (finishedTask == cancelTask)
            {
                try
                {
                    await sumPageSizesTask;
                    Console.WriteLine("在處理取消請求之前下載任務(wù)已完成。");
                }
                catch (OperationCanceledException)
                {
                    Console.WriteLine("下載任務(wù)已被取消。");
                }
            }

            Console.WriteLine("程序結(jié)束。");
        }

        static async Task SumPageSizesAsync()
        {
            var stopwatch = Stopwatch.StartNew();
            int total = 0;

            foreach (string url in s_urlList)
            {
                int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
                total += contentLength;
            }

            stopwatch.Stop();
            Console.WriteLine($"\n總計下載字節(jié)數(shù): {total:#,#}");
            Console.WriteLine($"耗時: {stopwatch.Elapsed}\n");
        }

        static async Task<int> ProcessUrlAsync(string url, HttpClient client, CancellationToken token)
        {
            HttpResponseMessage response = await client.GetAsync(url, token);
            byte[] content = await response.Content.ReadAsByteArrayAsync(token);
            Console.WriteLine($"{url,-60} {content.Length,10:#,#}");
            return content.Length;
        }
    }
}

代碼詳解

初始化設(shè)置 

static readonly CancellationTokenSource s_cts = new CancellationTokenSource();
static readonly HttpClient s_client = new HttpClient { MaxResponseContentBufferSize = 1_000_000 };
  • 創(chuàng)建CancellationTokenSource實(shí)例用于發(fā)出取消信號
  • 創(chuàng)建HttpClient實(shí)例用于發(fā)送HTTP請求
  • 使用static readonly確保這些實(shí)例在整個應(yīng)用程序生命周期內(nèi)只創(chuàng)建一次

主方法實(shí)現(xiàn) 

主方法使用async Task Main()實(shí)現(xiàn)異步入口點(diǎn),包含兩個主要任務(wù):

  1. 取消監(jiān)聽任務(wù)(cancelTask)
  2. 下載處理任務(wù)(sumPageSizesTask)

異步下載實(shí)現(xiàn) 

ProcessUrlAsync方法實(shí)現(xiàn)了單個URL的下載邏輯:

static async Task<int> ProcessUrlAsync(string url, HttpClient client, CancellationToken token)
{
    HttpResponseMessage response = await client.GetAsync(url, token);
    byte[] content = await response.Content.ReadAsByteArrayAsync(token);
    Console.WriteLine($"{url,-60} {content.Length,10:#,#}");
    return content.Length;
}
  • 使用GetAsync方法發(fā)送HTTP請求
  • 傳入CancellationToken支持取消操作
  • 返回下載內(nèi)容的字節(jié)數(shù)

運(yùn)行效果

程序運(yùn)行后會顯示如下輸出:

圖片圖片

注意

  1. 始終使用using語句或字段初始化方式創(chuàng)建CancellationTokenSource
  2. 在所有可取消的異步操作中傳遞CancellationToken
  3. 正確處理取消異常
  4. 使用static readonly創(chuàng)建長期使用的HTTP客戶端實(shí)例

總結(jié)

這種模式適用于需要支持用戶取消的長時間運(yùn)行的異步操作,如網(wǎng)絡(luò)請求、文件下載等場景。

責(zé)任編輯:武曉燕 來源: 技術(shù)老小子
相關(guān)推薦

2021-10-12 17:47:22

C# TAP異步

2015-09-16 15:11:58

C#異步編程

2009-08-20 17:30:56

C#異步編程模式

2009-08-21 10:13:02

C#異步初步

2010-12-22 10:21:17

C#基礎(chǔ)

2024-04-09 08:04:42

C#結(jié)構(gòu)await

2024-03-04 18:49:59

反射C#開發(fā)

2009-08-25 17:13:57

C#串口編程

2012-07-27 10:02:39

C#

2009-04-10 09:55:44

C#反射.NET

2009-08-20 16:33:44

Socket異步通訊

2024-12-23 09:09:54

2009-08-25 10:44:08

C#接口定義接口

2009-08-25 10:57:09

C#接口

2009-08-20 17:47:54

C#異步編程模式

2016-12-14 15:05:08

C#異步編程

2024-10-15 08:29:09

C#軟件開發(fā)

2016-09-07 20:43:36

Javascript異步編程

2009-08-07 16:19:00

C#下數(shù)據(jù)庫編程

2009-08-07 16:19:00

C#下數(shù)據(jù)庫編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號