C# 并发任务取消CancellationToken的详细使用教程

CancellationToken 是 C# 中用于取消异步任务的机制,广泛应用于任务并行库(Task Parallel Library,TPL)、异步方法以及其他需要支持取消操作的多线程场景。使用 CancellationToken,可以在异步任务中提供一个取消信号,使得任务在必要时能够及时中止执行。

下面是 CancellationToken 的详细使用教程,涵盖其基本概念、使用方法以及一些高级应用场景。

目录

  1. 什么是 CancellationToken
  2. 使用 CancellationToken 的步骤
  3. 详细使用示例
  4. 进阶用法
  5. 注意事项
  6. 总结

1. 什么是 CancellationToken

CancellationToken 是用于在异步或并行操作中传递取消请求的结构。它通常和 CancellationTokenSource 一起使用。CancellationTokenSource 是管理取消信号的对象,而 CancellationToken 则是用于检测是否收到取消请求的标志。

  • CancellationTokenSource:生成并管理取消请求。
  • CancellationToken:由 CancellationTokenSource 提供,任务使用它来检查取消信号。

2. 使用 CancellationToken 的步骤

  1. 创建 CancellationTokenSource 对象

    • CancellationTokenSource 是用来生成 CancellationToken 的对象,它控制取消信号。
  2. CancellationToken 传递给异步任务

    • CancellationToken 是通过 CancellationTokenSource 提供的,用于向任务传递取消信号。
  3. 在任务中检查取消状态

    • 任务需要定期检查 CancellationToken,并在收到取消请求时,停止执行。
  4. 请求取消

    • 调用 CancellationTokenSource.Cancel() 来发出取消请求,通知关联的任务。

3. 详细使用示例

3.1 创建并取消任务的基础示例
using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        // 1. 创建 CancellationTokenSource
        CancellationTokenSource cts = new CancellationTokenSource();
        CancellationToken token = cts.Token;

        // 2. 启动任务并传递 token
        Task task = Task.Run(() => DoWork(token), token);

        // 模拟用户请求取消任务
        Console.WriteLine("Press any key to cancel the task...");
        Console.ReadKey();

        // 3. 请求取消
        cts.Cancel();

        try
        {
            // 4. 等待任务完成
            await task;
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Task was cancelled.");
        }
        finally
        {
            cts.Dispose();
        }

        Console.WriteLine("Main program has completed.");
    }

    static void DoWork(CancellationToken token)
    {
        for (int i = 0; i < 10; i++)
        {
            // 检查任务是否被取消
            token.ThrowIfCancellationRequested();

            Console.WriteLine($"Task working... {i}");
            Thread.Sleep(500);  // 模拟耗时操作
        }

        Console.WriteLine("Task completed.");
    }
}
代码说明
  1. 创建 CancellationTokenSource:用于管理取消操作。
  2. 传递 CancellationToken:在任务启动时传递 CancellationToken,任务可以通过它检查是否有取消请求。
  3. 定期检查取消状态:使用 token.ThrowIfCancellationRequested() 检查任务是否被取消,并抛出 OperationCanceledException 以中止任务。
  4. 发出取消请求:调用 cts.Cancel() 来通知任务取消。
  5. 处理取消异常:捕获 OperationCanceledException 以处理取消后的清理工作。

3.2 使用 token.IsCancellationRequested 检查取消状态

有时,不需要抛出异常,而是通过检查 token.IsCancellationRequested 来有条件地终止任务。

static void DoWork(CancellationToken token)
{
    for (int i = 0; i < 10; i++)
    {
        if (token.IsCancellationRequested)
        {
            Console.WriteLine("Task is cancelling...");
            break;  // 退出循环,停止任务
        }

        Console.WriteLine($"Task working... {i}");
        Thread.Sleep(500);  // 模拟耗时操作
    }

    Console.WriteLine("Task completed.");
}
3.3 设置超时取消任务

CancellationTokenSource 提供了一些辅助方法,比如设置超时来自动取消任务。

CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));  // 5秒后自动取消
CancellationToken token = cts.Token;

try
{
    Task task = Task.Run(() => DoWork(token), token);
    await task;
}
catch (OperationCanceledException)
{
    Console.WriteLine("Task was cancelled due to timeout.");
}

4. 进阶用法

4.1 合并多个 CancellationToken

有时一个任务可能同时需要响应多个取消请求,可以通过 CancellationTokenSource.CreateLinkedTokenSource 来合并多个 CancellationToken

CancellationTokenSource cts1 = new CancellationTokenSource();
CancellationTokenSource cts2 = new CancellationTokenSource();

// 合并两个 token
CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
CancellationToken token = linkedCts.Token;

Task task = Task.Run(() => DoWork(token), token);

// 发出取消请求
cts1.Cancel();  // 或 cts2.Cancel();
4.2 使用 CancellationToken 取消异步方法

异步方法也支持 CancellationToken,可以在异步操作中使用。

static async Task DoWorkAsync(CancellationToken token)
{
    for (int i = 0; i < 10; i++)
    {
        // 检查取消请求
        token.ThrowIfCancellationRequested();

        // 模拟异步操作
        await Task.Delay(1000);
        Console.WriteLine($"Working... {i}");
    }
}

5. 注意事项

  • 定期检查取消状态:在任务内部定期调用 token.ThrowIfCancellationRequested()token.IsCancellationRequested 来检测取消信号,确保任务能够及时响应取消请求。
  • 取消任务的副作用:如果任务涉及到 I/O 操作、文件写入等,需要确保在取消后执行适当的清理工作,防止资源泄漏。
  • 处理 OperationCanceledException:通常使用 try-catch 来捕获 OperationCanceledException,以确保任务取消后程序能正确处理。
  • 不可取消的操作:一些耗时的阻塞操作(如 Thread.Sleep())是无法响应取消请求的,使用 Task.Delay() 等非阻塞操作会更好地配合取消机制。

6. 总结

CancellationToken 为 C# 中的异步任务和并行操作提供了灵活的取消机制。通过合理地使用 CancellationTokenSourceCancellationToken,可以让任务在适当的时刻取消执行,避免不必要的资源浪费。掌握如何通过 token.ThrowIfCancellationRequested()token.IsCancellationRequested 检测取消请求,是异步和并发编程中的关键技巧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

生命不息-学无止境

你的每一份支持都是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值