当前位置:首页 > C# > 正文

C#并行循环的取消处理(使用CancellationToken优雅终止Parallel.For/ForEach)

在C#开发中,当我们需要处理大量数据或执行耗时操作时,并行循环(如 Parallel.ForParallel.ForEach)是提升性能的常用手段。然而,在某些场景下(例如用户点击“取消”按钮、程序需要提前退出等),我们希望能够安全、及时地取消正在进行的并行任务。本文将手把手教你如何在C#中使用 CancellationToken 实现并行循环的取消处理,即使是编程新手也能轻松掌握。

C#并行循环的取消处理(使用CancellationToken优雅终止Parallel.For/ForEach) C#并行循环 Parallel.For取消 任务取消令牌 CancellationToken并行处理 第1张

为什么需要取消并行循环?

想象一下:你的程序正在用 Parallel.For 处理一百万个数据项,但用户突然想停止这个操作。如果没有取消机制,程序会继续运行直到完成,浪费系统资源,甚至可能导致界面卡死。因此,引入任务取消令牌(CancellationToken)就显得尤为重要。

核心概念:CancellationToken

CancellationToken 是 .NET 提供的一种标准机制,用于在多个线程或任务之间传递“取消请求”。它通常与 CancellationTokenSource 配合使用:

  • CancellationTokenSource:负责发出取消信号。
  • CancellationToken:由 CancellationTokenSource 创建,传递给需要监听取消请求的代码。

实战:在 Parallel.For 中实现取消

下面是一个完整的示例,演示如何在 Parallel.For 中响应取消请求:

using System;using System.Threading;using System.Threading.Tasks;class Program{    static void Main()    {        // 创建 CancellationTokenSource        var cts = new CancellationTokenSource();        // 模拟用户在5秒后点击“取消”        Task.Run(() =>        {            Thread.Sleep(5000);            Console.WriteLine("\n用户请求取消...");            cts.Cancel();        });        try        {            // 执行并行循环,并传入 CancellationToken            Parallel.For(0, 1000000, new ParallelOptions            {                CancellationToken = cts.Token            }, (i, state) =>            {                // 检查是否收到取消请求                cts.Token.ThrowIfCancellationRequested();                // 模拟耗时操作                Thread.Sleep(10);                if (i % 10000 == 0)                    Console.WriteLine($"处理第 {i} 项...");            });            Console.WriteLine("\n所有任务已完成!");        }        catch (OperationCanceledException)        {            Console.WriteLine("\n并行循环已被成功取消。");        }        finally        {            cts.Dispose();        }        Console.WriteLine("按任意键退出...");        Console.ReadKey();    }}

代码解析:

  1. 创建 CancellationTokenSource(cts),用于控制取消。
  2. 启动一个后台任务,在5秒后调用 cts.Cancel() 发出取消信号。
  3. Parallel.For 中通过 ParallelOptions 传入 cts.Token
  4. 在循环体内部,定期调用 ThrowIfCancellationRequested() —— 如果收到取消请求,该方法会抛出 OperationCanceledException
  5. 捕获异常并友好提示“已被取消”。

注意事项与最佳实践

  • 频繁检查取消请求:在循环体内定期调用 ThrowIfCancellationRequested() 或检查 IsCancellationRequested 属性,确保能及时响应。
  • 使用 ParallelOptions:必须通过 ParallelOptionsCancellationToken 传递给 Parallel.ForParallel.ForEach,否则无法生效。
  • 资源清理:记得在 finally 块中释放 CancellationTokenSource(调用 Dispose())。
  • ⚠️ 取消不是立即停止:已启动的迭代可能继续运行,直到它们主动检查取消令牌。因此,设计时要考虑“协作式取消”。

总结

通过本文,你已经掌握了如何在 C# 中使用 CancellationToken 安全地取消 Parallel.ForParallel.ForEach。这种模式不仅适用于并行循环,也广泛应用于 Task、异步方法等场景。记住:C#并行循环 的取消处理是构建响应式、健壮应用程序的关键技能之一。

关键词回顾:C#并行循环、Parallel.For取消、任务取消令牌、CancellationToken并行处理。