C# 中 CancellationTokenSource 的使用详解与实战示例

文章摘要

本文将介绍在 C# 中如何使用 CancellationTokenSource 类来实现异步任务的取消机制。我们将探讨 CancellationTokenSource 的主要属性和方法,并通过一个实际的例子来展示如何在 WinForms 应用程序中使用 CancellationTokenSource 来取消长时间运行的异步任务。通过本文,你将了解到如何有效地管理异步任务的取消,提高应用程序的响应性和健壮性。


如何使用 C# 中的 CancellationTokenSource

在开发现代应用程序时,异步编程已成为处理长时间运行任务的标准做法。然而,随着异步任务的增加,如何优雅地取消这些任务成为了一个重要的问题。CancellationTokenSource 类提供了强大的工具来实现这一目标。本文将详细介绍 CancellationTokenSource 的主要属性和方法,并通过一个具体的示例来展示如何使用它。

1. CancellationTokenSource 类简介

CancellationTokenSource 是 C# 中用于实现异步操作取消的核心类之一。它生成 CancellationToken 对象,该对象可以传递给异步方法,并在异步方法内部检查是否应取消该操作。

2. CancellationTokenSource 类的主要属性
  • Token
    • 类型CancellationToken
    • 用途:获取一个 CancellationToken 对象,用于监视取消请求的状态。
    • 示例
      CancellationTokenSource cts = new CancellationTokenSource();
      CancellationToken token = cts.Token;
      
3. CancellationTokenSource 类的主要方法
  • Cancel()

    • 作用:取消当前的取消令牌,使其处于已取消状态。
    • 示例
      CancellationTokenSource cts = new CancellationTokenSource();
      cts.Cancel(); // 请求取消
      
  • CancelAfter(TimeSpan delay)

    • 作用:延迟一段时间后取消当前的取消令牌。
    • 参数
      • TimeSpan delay:延迟取消的时间。
    • 示例
      CancellationTokenSource cts = new CancellationTokenSource();
      cts.CancelAfter(TimeSpan.FromSeconds(5)); // 5 秒后请求取消
      
  • CancelAfter(int millisecondsDelay)

    • 作用:延迟指定的毫秒数后取消当前的取消令牌。
    • 参数
      • int millisecondsDelay:延迟取消的时间(毫秒)。
    • 示例
      CancellationTokenSource cts = new CancellationTokenSource();
      cts.CancelAfter(5000); // 5 秒后请求取消
      
  • Dispose()

    • 作用:释放 CancellationTokenSource 占用的资源。
    • 示例
      CancellationTokenSource cts = new CancellationTokenSource();
      cts.Dispose(); // 释放资源
      
4. 如何使用 CancellationTokenSource

下面是一个完整的示例,展示了如何使用 CancellationTokenSource 来实现异步任务的取消。

示例代码
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsyncWinFormsApp
{
    public partial class MainForm : Form
    {
        private CancellationTokenSource _cancellationTokenSource;

        public MainForm()
        {
            InitializeComponent();
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            try
            {
                // 禁用按钮
                button1.Enabled = false;

                // 取消之前的任务
                CancelPreviousTask();

                // 显示等待提示
                label1.Text = "Processing...";

                // 调用异步方法
                await LongRunningTask();

                // 处理完成
                label1.Text = "Done!";
            }
            finally
            {
                // 重新启用按钮
                button1.Enabled = true;
            }
        }

        private void CancelPreviousTask()
        {
            _cancellationTokenSource?.Cancel();
            _cancellationTokenSource?.Dispose();
            _cancellationTokenSource = null;
        }

        private async Task LongRunningTask()
        {
            _cancellationTokenSource = new CancellationTokenSource();
            var cancellationToken = _cancellationTokenSource.Token;

            // 模拟长时间运行的任务
            for (int i = 0; i < 10; i++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    // 如果取消标记被请求,则停止执行
                    throw new OperationCanceledException();
                }

                await Task.Delay(1000, cancellationToken); // 暂停 1 秒
                Console.WriteLine($"Processing step {i + 1}...");
            }
        }

        private void cancelButton_Click(object sender, EventArgs e)
        {
            _cancellationTokenSource?.Cancel();
        }

        private void UpdateLabel(string text)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string>(UpdateLabel), text);
            }
            else
            {
                label1.Text = text;
            }
        }
    }
}
解释
  1. 创建 CancellationTokenSource

    • LongRunningTask 方法中创建一个 CancellationTokenSource,并从其中获取 CancellationToken
  2. 检查取消标记

    • 在循环中检查 cancellationToken.IsCancellationRequested 是否为 true。如果是,抛出 OperationCanceledException
  3. 使用 Task.Delay

    • 调用 Task.Delay(1000, cancellationToken) 来延迟 1 秒。如果在延迟期间取消标记被触发,延迟操作会被取消。
  4. 取消操作

    • 当用户点击取消按钮时,调用 _cancellationTokenSource.Cancel() 来请求取消当前的任务。
5. CancellationTokenSource 的注意事项
  • 不要重复使用 CancellationTokenSource

    • 一旦 CancellationTokenSource 被取消,就不能再被重用。如果需要取消另一个任务,应该创建一个新的 CancellationTokenSource
  • 及时释放资源

    • 使用完 CancellationTokenSource 后,记得调用 Dispose() 方法来释放资源。这有助于避免资源泄漏。
  • 取消标记的传播

    • 如果一个异步方法需要将取消标记传递给其他方法,可以将 CancellationToken 作为参数传递下去,并在内部继续检查是否需要取消。

通过上述方法,你可以有效地管理异步任务的取消,从而提高应用程序的响应性和健壮性。希望这篇文章对你有所帮助,如果你有任何具体的问题或需要进一步的帮助,请随时留言交流!


通过本文的介绍,你不仅了解了 CancellationTokenSource 的基本用法,还学会了如何在实际应用中运用这一机制来增强应用程序的用户体验。在未来的开发中,合理地使用 CancellationTokenSource 可以让你的应用程序更加灵活和可靠。

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值