C# 中取消任务(Task)的正确方式

开发 前端
CancellationToken​ 是一个结构,用于传递取消操作的通知,如用户请求取消或超时。CancellationTokenSource​ 是用于生成 CancellationToken 的类,并提供了取消该令牌的方法。

在C#中,异步编程是处理耗时操作,如I/O请求、数据库调用或网络请求等,而不阻塞主线程的一种有效方法。Task 类是这种异步操作的核心,它允许我们启动异步操作并等待其完成。然而,有时我们可能需要在任务完成之前取消它,特别是当任务依赖于某些外部条件或用户交互时。在C#中,取消任务通常通过使用 CancellationToken 来实现。

CancellationToken 和 CancellationTokenSource

CancellationToken 是一个结构,用于传递取消操作的通知,如用户请求取消或超时。CancellationTokenSource 是用于生成 CancellationToken 的类,并提供了取消该令牌的方法。

下面是一个简单的示例,展示了如何使用 CancellationToken 和 CancellationTokenSource 来取消一个任务:

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        using CancellationTokenSource cts = new CancellationTokenSource();
        CancellationToken cancellationToken = cts.Token;

        // 启动一个可以被取消的任务
        Task myTask = Task.Run(() => DoWork(cancellationToken), cancellationToken);

        // 假设一段时间后,我们决定取消任务
        await Task.Delay(2000); // 等待2秒
        Console.WriteLine("Cancelling the task...");
        cts.Cancel(); // 发送取消信号

        try
        {
            await myTask; // 等待任务完成或捕获到OperationCanceledException异常
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Task was cancelled");
        }
    }

    static void DoWork(CancellationToken cancellationToken)
    {
        for (int i = 0; i < 10; i++)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                Console.WriteLine("Cancellation requested.");
                // 检查取消标记,如果已请求取消,则退出循环或执行其他清理操作
                break; // 或者返回,抛出OperationCanceledException等。
            }
            // 模拟工作正在进行中...
            Thread.Sleep(500); // 不要在生产代码中使用Thread.Sleep! 这里只是为了示例。
            Console.WriteLine("Working...");
        }
    }
}

在这个示例中,我们创建了一个 CancellationTokenSource 实例,并使用其 Token 属性生成了一个 CancellationToken。然后,我们将这个令牌传递给了一个在后台运行的任务(通过 Task.Run)。稍后,我们决定取消这个任务,于是调用了 CancellationTokenSource.Cancel 方法来提供取消信号。在任务代码中,我们定期检查取消标记,如果已请求取消,则退出循环。

注意事项和最佳实践:

  1. 定期检查取消标记:在你的任务代码中,你应该定期检查 CancellationToken.IsCancellationRequested 属性,以便在收到取消请求时能够迅速响应。
  2. 处理取消请求:当检测到取消请求时,你的代码应该尽快停止当前的操作并退出。你可以通过抛出 OperationCanceledException 异常、返回或执行其他适当的清理操作来实现这一点。
  3. 使用正确的等待方式:在等待可能被取消的任务时,最好使用 await 关键字而不是 Task.Wait() 或 Task.Result,因为后者在任务被取消时会抛出 AggregateException 而不是 OperationCanceledException,这可能会使异常处理更加复杂。
  4. 资源清理:确保在取消操作后妥善处理和清理所有已分配的资源,以避免内存泄漏或其他潜在问题。这包括关闭文件句柄、释放数据库连接等。
  5. 文档和测试:如果你的方法接受一个 CancellationToken 参数,确保在方法的文档中明确说明这一点,并编写针对取消操作的单元测试,以确保你的代码在收到取消信号时能够正确响应。
责任编辑:武晓燕 来源: 程序员编程日记
相关推荐

2024-05-13 11:36:56

C#线程

2024-04-01 11:30:57

C#拷贝

2024-05-11 07:13:33

C#Task编程

2011-08-29 10:35:53

反射方式C#

2024-03-06 13:23:56

Task.RunC#异步陷阱

2011-03-25 09:08:49

C#

2009-06-24 10:49:16

JavaScript

2009-05-13 11:50:17

C#多继承接口

2024-06-20 11:52:44

C#占位符代码

2024-05-16 11:04:06

C#异步编程编程

2009-07-31 18:28:46

实现C#显示图像

2024-09-13 08:27:00

2009-05-26 16:33:48

PythonC#Run As

2010-06-02 16:36:38

连接MySQL中文乱码

2023-03-10 22:14:49

KustomizeKubernetes

2010-02-05 14:12:46

C++声明放置

2024-04-02 09:26:07

C#中文数字编程语言

2010-06-07 08:43:46

.NET 4并行编程

2024-04-15 16:11:33

C#HTTP请求.NET

2009-01-19 10:26:02

C#Namespace.NET
点赞
收藏

51CTO技术栈公众号