20、Task取消操作

Task 取消操作

知识点

取消机制基础

  • CancellationToken:表示取消请求的令牌,用于检查是否有取消请求
  • CancellationTokenSource:取消令牌的源,用于发起取消请求
  • 协作式取消:任务需要主动检查取消令牌并响应取消请求
  • OperationCanceledException:取消操作时抛出的标准异常

取消模式

  • 轮询检查:定期检查 CancellationToken.IsCancellationRequested
  • 抛出异常:调用 CancellationToken.ThrowIfCancellationRequested()
  • 取消回调:使用 CancellationToken.Register() 注册取消回调
  • 超时取消:使用 CancellationTokenSource.CancelAfter() 设置超时

取消传播

  • 任务链取消:取消可以沿着任务链传播
  • 并行取消:多个任务可以响应同一个取消令牌
  • 嵌套取消:子取消令牌可以与父取消令牌关联
  • 组合取消:多个取消条件的组合

代码样例

基本取消操作

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

public class BasicCancellationDemo
{
    public static void DemonstrateBasicCancellation()
    {
        Console.WriteLine("=== 基本取消操作演示 ===");

        // 1. 简单的任务取消
        Console.WriteLine("1. 简单的任务取消:");
        DemonstrateSimpleTaskCancellation();

        // 2. 带返回值的任务取消
        Console.WriteLine("\n2. 带返回值的任务取消:");
        DemonstrateTaskWithResultCancellation();

        // 3. 超时取消
        Console.WriteLine("\n3. 超时取消:");
        DemonstrateTimeoutCancellation();

        Console.WriteLine("基本取消操作演示完成\n");
    }

    private static void DemonstrateSimpleTaskCancellation()
    {
        using (var cts = new CancellationTokenSource())
        {
            Task task = Task.Run(() =>
            {
                Console.WriteLine("  任务开始执行...");

                for (int i = 0; i < 10; i++)
                {
                    // 检查取消请求
                    cts.Token.ThrowIfCancellationRequested();

                    Console.WriteLine($"    工作进度: {i + 1}/10");
                    Thread.Sleep(500);
                }

                Console.WriteLine("  任务正常完成");
            }, cts.Token);

            // 2秒后请求取消
            Task.Run(async () =>
            {
                await Task.Delay(2000);
                Console.WriteLine("  发起取消请求...");
                cts.Cancel();
            });

            try
            {
                task.Wait();
                Console.WriteLine("  任务成功完成");
            }
            catch (AggregateException ex) when (ex.InnerException is OperationCanceledException)
            {
                Console.WriteLine("  任务被取消");
            }

            Console.WriteLine($"  任务最终状态: {task.Status}");
        }
    }

    private static void DemonstrateTaskWithResultCancellation()
    {
        using (var cts = new CancellationTokenSource())
        {
            Task<int> calculationTask = Task.Run(() =>
            {
                Console.WriteLine("  开始复杂计算...");
                int result = 0;

                for (int i = 0; i < 1000000; i++)
                {
                    // 每1000次迭代检查一次取消
                    if (i % 1000 == 0)
                    {
                        cts.Token.ThrowIfCancellationRequested();
                    }

                    result += i;

                    // 每100000次迭代显示进度
                    if (i % 100000 == 0)
                    {
                        Console.WriteLine($"    计算进度: {i / 10000}%");
                    }
                }

                Console.WriteLine("  计算完成");
                return result;
            }, cts.Token);

            // 1.5秒后取消
            cts.CancelAfter(1500);

            try
            {
                int result = calculationTask.Result;
                Console.WriteLine($"  计算结果: {result}");
            }
            catch (AggregateException ex) when (ex.InnerException is OperationCanceledException)
            {
                Console.WriteLine("  计算被取消");
            }

            Console.WriteLine($"  计算任务状态: {calculationTask.Status}");
        }
    }

    private static void DemonstrateTimeoutCancellation()
    {
        Console.WriteLine("  演示不同超时时间的效果:");

        var timeouts = new[] { 500, 1500, 3000 };

        foreach (int timeout in timeouts)
        {
            Console.WriteLine($"\n  测试 {timeout}ms 超时:");

            using (var cts = new CancellationTokenSource())
            {
                Task<string> task = Task.Run(() =>
                {
                    Console.WriteLine($"    任务开始 (预计运行2秒)");

                    for (int i = 0; i < 20; i++)
                    {
                        cts.Token.ThrowIfCancellationRequested();
                        Thread.Sleep(100);
                    }

                    return "任务完成";
                }, cts.Token);

                // 设置超时
                cts.CancelAfter(timeout);

                try
                {
                    string result = task.Result;
                    Console.WriteLine($"    结果: {result}");
                }
                catch (AggregateException ex) when (ex.InnerException is OperationCanceledException)
                {
                    Console.WriteLine($"    任务在 {timeout}ms 后被取消");
                }
            }
        }
    }
}

高级取消模式

public class AdvancedCancellationDemo
{
    public static void DemonstrateAdvancedCancellation()
    {
        Console.WriteLine("=== 高级取消模式演示 ===");

        // 1. 取消回调
        Console.WriteLine("1. 取消回调:");
        DemonstrateCancellationCallbacks();

        // 2. 嵌套取消令牌
        Console.WriteLine("\n2. 嵌套取消令牌:");
        DemonstrateNestedCancellationTokens();

        // 3. 多条件组合取消
        Console.WriteLine("\n3. 多条件组合取消:");
        DemonstrateCombinedCancellation();

        Console.WriteLine("高级取消模式演示完成\n");
    }

    private static void DemonstrateCancellationCallbacks()
    {
        using (var cts = new CancellationTokenSource())
        {
            // 注册取消回调
            var registration1 = cts.Token.Register(() =>
            {
                Console.WriteLine("  回调1: 清理资源A");
            });

            var registration2 = cts.Token.Register(() =>
            {
                Console.WriteLine("  回调2: 清理资源B");
            });

            var registration3 = cts.Token.Register(state =>
            {
                Console.WriteLine($"  回调3: 清理 {state}");
            }, "自定义资源");

            Task longRunningTask = Task.Run(() =>
            {
                Console.WriteLine("  长时间运行的任务开始...");

                try
                {
                    for (int i = 0; i < 50; i++)
                    {
                        cts.Token.ThrowIfCancellationRequested();
                        Thread.Sleep(100);

                        if (i % 10 == 0)
                        {
                            Console.WriteLine($"    任务进度: {i}/50");
                        }
                    }

                    Console.WriteLine("  任务正常完成");
                }
                catch (OperationCanceledException)
                {
                    Console.WriteLine("  任务收到取消信号");
                    throw;
                }
            }, cts.Token);

            // 2秒后取消
            Task.Run(async () =>
            {
                await Task.Delay(2000);
                Console.WriteLine("  发起取消请求...");
                cts.Cancel();
            });

            try
            {
                longRunningTask.Wait();
            }
            catch (AggregateException ex) when (ex.InnerException is OperationCanceledException)
            {
                Console.WriteLine("  任务已被取消");
            }

            // 清理注册
            registration1.Dispose();
            registration2.Dispose();
            registration3.Dispose();
        }
    }

    private static void DemonstrateNestedCancellationTokens()
    {
        using (var parentCts = new CancellationTokenSource())
        using (var childCts = new CancellationTokenSource())
        {
            // 创建组合的取消令牌
            using (var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(
                parentCts.Token, childCts.Token))
            {
                Task task = Task.Run(() =>
                {
                    Console.WriteLine("  组合取消任务开始...");

                    for (int i = 0; i < 100; i++)
                    {
                        // 检查组合的取消令牌
                        combinedCts.Token.ThrowIfCancellationRequested();

                        Thread.Sleep(50);

                        if (i % 20 == 0)
                        {
                            Console.WriteLine($"    进度: {i}%");
                        }
                    }

                    Console.WriteLine("  任务完成");
                }, combinedCts.Token);

                // 随机选择父级或子级取消
                Task.Run(async () =>
                {
                    await Task.Delay(1500);

                    if (new Random().Next(2) == 0)
                    {
                        Console.WriteLine("  父级取消源发起取消...");
                        parentCts.Cancel();
                    }
                    else
                    {
                        Console.WriteLine("  子级取消源发起取消...");
                        childCts.Cancel();
                    }
                });

                try
                {
                    task.Wait();
                    Console.WriteLine("  任务成功完成");
                }
                catch (AggregateException ex) when (ex.InnerException is OperationCanceledException)
                {
                    Console.WriteLine("  任务被取消");
                    Console.WriteLine($"    父级是否取消: {parentCts.Token.IsCancellationRequested}");
                    Console.WriteLine($"    子级是否取消: {childCts.Token.IsCancellationRequested}");
                    Console.WriteLine($"    组合是否取消: {combinedCts.Token.IsCancellationRequested}");
                }
            }
        }
    }

    private static void DemonstrateCombinedCancellation()
    {
        using (var userCts = new CancellationTokenSource())     // 用户取消
        using (var timeoutCts = new CancellationTokenSource())  // 超时取消
        using (var systemCts = new CancellationTokenSource())   // 系统取消
        {
            // 创建组合取消令牌
            using (var combinedCts = CancellationTokenSource.CreateLinkedTokenSource(
                userCts.Token, timeoutCts.Token, systemCts.Token))
            {
                Task<string> task = Task.Run(() =>
                {
                    Console.WriteLine("  多条件取消任务开始...");

                    for (int i = 0; i < 60; i++)
                    {
                        combinedCts.Token.ThrowIfCancellationRequested();

                        Thread.Sleep(100);

                        if (i % 15 == 0)
                        {
                            Console.WriteLine($"    运行时间: {i / 10.0}秒");
                        }
                    }

                    return "任务成功完成";
                }, combinedCts.Token);

                // 设置不同的取消条件
                timeoutCts.CancelAfter(3000);  // 3秒超时

                // 模拟用户在2秒后取消
                Task.Run(async () =>
                {
                    await Task.Delay(2000);
                    if (new Random().Next(3) == 0)
                    {
                        Console.WriteLine("  用户请求取消...");
                        userCts.Cancel();
                    }
                });

                // 模拟系统在2.5秒后取消
                Task.Run(async () =>
                {
                    await Task.Delay(2500);
                    if (new Random().Next(3) == 0)
                    {
                        Console.WriteLine("  系统请求取消...");
                        systemCts.Cancel();
                    }
                });

                try
                {
                    string result = task.Result;
                    Console.WriteLine($"  结果: {result}");
                }
                catch (AggregateException ex) when (ex.InnerException is OperationCanceledException)
                {
                    Console.WriteLine("  任务被取消,原因分析:");

                    if (userCts.Token.IsCancellationRequested)
                        Console.WriteLine("    - 用户取消");
                    if (timeoutCts.Token.IsCancellationRequested)
                        Console.WriteLine("    - 超时取消");
                    if (systemCts.Token.IsCancellationRequested)
                        Console.WriteLine("    - 系统取消");
                }
            }
        }
    }
}

异步方法中的取消

public class AsyncCancellationDemo
{
    public static void DemonstrateAsyncCancellation()
    {
        Console.WriteLine("=== 异步方法中的取消演示 ===");

        // 1. async/await 模式的取消
        Console.WriteLine("1. async/await 模式的取消:");
        DemonstrateAsyncAwaitCancellation().Wait();

        // 2. 多级异步调用的取消传播
        Console.WriteLine("\n2. 多级异步调用的取消传播:");
        DemonstrateAsyncCancellationPropagation().Wait();

        // 3. 并行异步操作的取消
        Console.WriteLine("\n3. 并行异步操作的取消:");
        DemonstrateParallelAsyncCancellation().Wait();

        Console.WriteLine("异步方法取消演示完成\n");
    }

    private static async Task DemonstrateAsyncAwaitCancellation()
    {
        using (var cts = new CancellationTokenSource())
        {
            // 3秒后自动取消
            cts.CancelAfter(3000);

            try
            {
                string result = await PerformAsyncOperationAsync(cts.Token);
                Console.WriteLine($"  异步操作结果: {result}");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("  异步操作被取消");
            }
        }
    }

    private static async Task<string> PerformAsyncOperationAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("  开始异步操作...");

        for (int i = 0; i < 10; i++)
        {
            // 异步等待,同时检查取消
            await Task.Delay(500, cancellationToken);
            Console.WriteLine($"    异步步骤 {i + 1}/10 完成");
        }

        return "异步操作完成";
    }

    private static async Task DemonstrateAsyncCancellationPropagation()
    {
        using (var cts = new CancellationTokenSource())
        {
            // 2秒后取消
            cts.CancelAfter(2000);

            try
            {
                await Level1AsyncMethod(cts.Token);
                Console.WriteLine("  多级异步调用完成");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("  多级异步调用被取消");
            }
        }
    }

    private static async Task Level1AsyncMethod(CancellationToken cancellationToken)
    {
        Console.WriteLine("  级别1 异步方法开始");
        await Task.Delay(300, cancellationToken);

        await Level2AsyncMethod(cancellationToken);

        Console.WriteLine("  级别1 异步方法完成");
    }

    private static async Task Level2AsyncMethod(CancellationToken cancellationToken)
    {
        Console.WriteLine("    级别2 异步方法开始");
        await Task.Delay(400, cancellationToken);

        await Level3AsyncMethod(cancellationToken);

        Console.WriteLine("    级别2 异步方法完成");
    }

    private static async Task Level3AsyncMethod(CancellationToken cancellationToken)
    {
        Console.WriteLine("      级别3 异步方法开始");

        for (int i = 0; i < 5; i++)
        {
            await Task.Delay(300, cancellationToken);
            Console.WriteLine($"        级别3 步骤 {i + 1}/5");
        }

        Console.WriteLine("      级别3 异步方法完成");
    }

    private static async Task DemonstrateParallelAsyncCancellation()
    {
        using (var cts = new CancellationTokenSource())
        {
            // 2.5秒后取消
            cts.CancelAfter(2500);

            try
            {
                // 创建多个并行的异步任务
                Task[] tasks = new Task[]
                {
                    CreateAsyncTask("任务A", 1000, cts.Token),
                    CreateAsyncTask("任务B", 1500, cts.Token),
                    CreateAsyncTask("任务C", 2000, cts.Token),
                    CreateAsyncTask("任务D", 3000, cts.Token)
                };

                await Task.WhenAll(tasks);
                Console.WriteLine("  所有并行任务完成");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("  并行任务被取消");
            }
        }
    }

    private static async Task CreateAsyncTask(string taskName, int duration, CancellationToken cancellationToken)
    {
        Console.WriteLine($"  {taskName} 开始 (预计运行 {duration}ms)");

        try
        {
            await Task.Delay(duration, cancellationToken);
            Console.WriteLine($"  {taskName} 完成");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine($"  {taskName} 被取消");
            throw; // 重新抛出,让调用者知道取消发生了
        }
    }
}

优雅关闭模式

public class GracefulShutdownDemo
{
    public class DataProcessor
    {
        private readonly CancellationTokenSource _shutdownCts = new CancellationTokenSource();
        private Task _processingTask;
        private bool _isRunning = false;

        public void Start()
        {
            if (_isRunning)
                return;

            _isRunning = true;
            _processingTask = ProcessDataContinuously(_shutdownCts.Token);
            Console.WriteLine("数据处理器已启动");
        }

        public async Task StopAsync(TimeSpan timeout = default)
        {
            if (!_isRunning)
                return;

            Console.WriteLine("开始优雅关闭数据处理器...");

            // 发起取消请求
            _shutdownCts.Cancel();

            try
            {
                // 等待处理任务完成
                if (timeout == default)
                    timeout = TimeSpan.FromSeconds(10);

                await _processingTask.WaitAsync(timeout);
                Console.WriteLine("数据处理器已优雅关闭");
            }
            catch (TimeoutException)
            {
                Console.WriteLine("等待超时,强制关闭数据处理器");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("数据处理器已被取消");
            }

            _isRunning = false;
        }

        private async Task ProcessDataContinuously(CancellationToken cancellationToken)
        {
            int processedCount = 0;

            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    // 处理一批数据
                    await ProcessBatch(processedCount + 1, cancellationToken);
                    processedCount++;

                    // 检查是否有取消请求
                    if (cancellationToken.IsCancellationRequested)
                    {
                        Console.WriteLine("收到关闭信号,正在完成当前批次...");
                        break;
                    }

                    // 等待下一个批次,可以被取消中断
                    await Task.Delay(1000, cancellationToken);
                }
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("数据处理被取消");
            }
            finally
            {
                // 清理资源
                Console.WriteLine($"清理资源,共处理了 {processedCount} 个批次");
            }
        }

        private async Task ProcessBatch(int batchNumber, CancellationToken cancellationToken)
        {
            Console.WriteLine($"  处理批次 {batchNumber}...");

            // 模拟批次处理,支持取消
            for (int i = 0; i < 5; i++)
            {
                cancellationToken.ThrowIfCancellationRequested();
                await Task.Delay(200, cancellationToken);
            }

            Console.WriteLine($"  批次 {batchNumber} 处理完成");
        }

        public void Dispose()
        {
            _shutdownCts?.Cancel();
            _shutdownCts?.Dispose();
        }
    }

    public static void DemonstrateGracefulShutdown()
    {
        Console.WriteLine("=== 优雅关闭模式演示 ===");

        var processor = new DataProcessor();

        try
        {
            // 启动处理器
            processor.Start();

            // 运行一段时间
            Console.WriteLine("让数据处理器运行 5 秒...");
            Thread.Sleep(5000);

            // 优雅关闭
            processor.StopAsync(TimeSpan.FromSeconds(3)).Wait();
        }
        finally
        {
            processor.Dispose();
        }

        Console.WriteLine("优雅关闭演示完成\n");
    }
}

实际应用场景

public class CancellationPracticalDemo
{
    public class FileDownloader
    {
        public async Task<string> DownloadFileAsync(string url, string filePath,
            IProgress<int> progress, CancellationToken cancellationToken)
        {
            Console.WriteLine($"开始下载: {url}");

            try
            {
                // 模拟下载过程
                for (int i = 0; i <= 100; i += 10)
                {
                    // 检查取消
                    cancellationToken.ThrowIfCancellationRequested();

                    // 模拟下载延迟
                    await Task.Delay(200, cancellationToken);

                    // 报告进度
                    progress?.Report(i);
                    Console.WriteLine($"  下载进度: {i}%");
                }

                Console.WriteLine($"下载完成: {filePath}");
                return filePath;
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine($"下载被取消: {url}");

                // 清理部分下载的文件
                Console.WriteLine("  清理部分下载的文件...");

                throw;
            }
        }
    }

    public class BatchProcessor
    {
        public async Task<int> ProcessItemsAsync<T>(IEnumerable<T> items,
            Func<T, CancellationToken, Task> processor,
            CancellationToken cancellationToken)
        {
            int processedCount = 0;
            var itemList = items.ToList();

            Console.WriteLine($"开始批量处理 {itemList.Count} 个项目");

            foreach (var item in itemList)
            {
                try
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    await processor(item, cancellationToken);
                    processedCount++;

                    Console.WriteLine($"  已处理: {processedCount}/{itemList.Count}");
                }
                catch (OperationCanceledException)
                {
                    Console.WriteLine($"批量处理被取消,已处理 {processedCount} 个项目");
                    throw;
                }
            }

            Console.WriteLine($"批量处理完成,共处理 {processedCount} 个项目");
            return processedCount;
        }
    }

    public static void DemonstratePracticalCancellation()
    {
        Console.WriteLine("=== 实际应用场景取消演示 ===");

        // 1. 文件下载取消
        Console.WriteLine("1. 文件下载取消:");
        DemonstrateFileDownloadCancellation().Wait();

        // 2. 批量处理取消
        Console.WriteLine("\n2. 批量处理取消:");
        DemonstrateBatchProcessingCancellation().Wait();

        // 3. 服务请求超时取消
        Console.WriteLine("\n3. 服务请求超时取消:");
        DemonstrateServiceRequestCancellation().Wait();

        Console.WriteLine("实际应用场景演示完成\n");
    }

    private static async Task DemonstrateFileDownloadCancellation()
    {
        var downloader = new FileDownloader();
        using (var cts = new CancellationTokenSource())
        {
            var progress = new Progress<int>(percentage =>
            {
                if (percentage >= 50)
                {
                    Console.WriteLine("  下载进度达到50%,用户请求取消...");
                    cts.Cancel();
                }
            });

            try
            {
                string result = await downloader.DownloadFileAsync(
                    "http://example.com/largefile.zip",
                    "largefile.zip",
                    progress,
                    cts.Token);

                Console.WriteLine($"  下载成功: {result}");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("  文件下载已取消");
            }
        }
    }

    private static async Task DemonstrateBatchProcessingCancellation()
    {
        var processor = new BatchProcessor();
        var items = Enumerable.Range(1, 10).ToArray();

        using (var cts = new CancellationTokenSource())
        {
            // 3秒后取消
            cts.CancelAfter(3000);

            try
            {
                int processed = await processor.ProcessItemsAsync(
                    items,
                    async (item, cancellationToken) =>
                    {
                        Console.WriteLine($"    处理项目 {item}");
                        await Task.Delay(400, cancellationToken);
                    },
                    cts.Token);

                Console.WriteLine($"  批量处理完成: {processed} 个项目");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("  批量处理已取消");
            }
        }
    }

    private static async Task DemonstrateServiceRequestCancellation()
    {
        var services = new[] { "ServiceA", "ServiceB", "ServiceC" };

        foreach (string service in services)
        {
            using (var cts = new CancellationTokenSource())
            {
                // 为每个服务设置不同的超时时间
                int timeout = service == "ServiceB" ? 800 : 1500; // ServiceB 超时更快
                cts.CancelAfter(timeout);

                try
                {
                    string result = await CallServiceAsync(service, cts.Token);
                    Console.WriteLine($"  {service} 调用成功: {result}");
                }
                catch (OperationCanceledException)
                {
                    Console.WriteLine($"  {service} 调用超时 ({timeout}ms)");
                }
            }
        }
    }

    private static async Task<string> CallServiceAsync(string serviceName, CancellationToken cancellationToken)
    {
        Console.WriteLine($"  调用 {serviceName}...");

        // 模拟不同的服务响应时间
        int delay = serviceName switch
        {
            "ServiceA" => 500,
            "ServiceB" => 1200,  // 这个会超时
            "ServiceC" => 600,
            _ => 1000
        };

        await Task.Delay(delay, cancellationToken);
        return $"来自 {serviceName} 的响应";
    }
}

综合演示

public class ComprehensiveCancellationDemo
{
    public static void RunAllDemos()
    {
        Console.WriteLine("Task 取消操作综合演示");
        Console.WriteLine("=".PadRight(60, '='));

        // 1. 基本取消操作
        BasicCancellationDemo.DemonstrateBasicCancellation();

        // 2. 高级取消模式
        AdvancedCancellationDemo.DemonstrateAdvancedCancellation();

        // 3. 异步方法中的取消
        AsyncCancellationDemo.DemonstrateAsyncCancellation();

        // 4. 优雅关闭模式
        GracefulShutdownDemo.DemonstrateGracefulShutdown();

        // 5. 实际应用场景
        CancellationPracticalDemo.DemonstratePracticalCancellation();

        Console.WriteLine("所有取消操作演示完成");
    }
}

总结

取消机制的核心概念

  1. 协作式取消:任务需要主动检查并响应取消请求
  2. CancellationToken:轻量级的取消信号载体,可以安全地传递和检查
  3. CancellationTokenSource:取消信号的发起者,负责管理取消状态
  4. OperationCanceledException:标准的取消异常,用于表示操作被取消

取消检查的最佳实践

  • 及时检查:在循环、长时间操作中定期检查取消状态
  • ThrowIfCancellationRequested():简洁的取消检查和异常抛出
  • Task.Delay(timeout, cancellationToken):在异步等待中支持取消
  • Register 回调:注册取消时的清理逻辑

高级取消模式

  1. 组合取消令牌:使用 CreateLinkedTokenSource 组合多个取消条件
  2. 超时取消:CancelAfter() 方法设置自动超时
  3. 嵌套取消:子操作继承父操作的取消令牌
  4. 取消回调:在取消时执行清理逻辑

异步取消的注意事项

  • 传递取消令牌:在异步调用链中一直传递 CancellationToken
  • Task.Delay 取消:使用支持取消的 Task.Delay 重载
  • 并行操作取消:确保所有并行任务都能响应取消
  • 异常处理:正确处理 OperationCanceledException

优雅关闭设计

  1. 发起取消信号:通过 CancellationTokenSource.Cancel() 发起关闭
  2. 等待完成:给正在进行的操作一定时间完成
  3. 清理资源:在 finally 块或 using 语句中清理资源
  4. 超时处理:设置最大等待时间,超时后强制关闭

常见应用场景

  1. 用户取消:响应用户的取消操作(如取消按钮)
  2. 超时处理:为长时间运行的操作设置超时
  3. 资源限制:在系统资源不足时取消低优先级操作
  4. 应用关闭:应用程序关闭时优雅地停止所有后台任务

性能和资源考虑

  • 取消令牌是轻量级的:可以安全地复制和传递
  • 及时释放资源:使用 using 语句管理 CancellationTokenSource
  • 避免过度检查:在性能敏感的循环中平衡检查频率
  • 回调注册管理:及时 Dispose 不再需要的回调注册
posted @ 2025-08-27 01:24  jessqiu  阅读(64)  评论(0)    收藏  举报