0Pricing
C# Academy · 课时

CancellationToken 模式与协作式取消

传递并遵守 CancellationToken:创建 CTS,轮询取消状态或因取消而抛出异常,将其传给异步 API,并通过注册进行清理。

CancellationToken 模式与协作式取消 是 CoddyKit 上的免费 C# Academy 课时。 这是第 1 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 3 节课。

协作式取消

目标:以协作方式取消工作。

  • 创建一个 CancellationTokenSource
  • 向下传递 CancellationToken
  • 检查 IsCancellationRequested,或调用 ThrowIfCancellationRequested()
  • 快速且妥善地响应取消

调用方驱动的取消

创建一个 CancellationTokenSource,传递令牌,并从调用方执行取消;被调用方会抛出 OperationCanceledException。

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

public class Program
{
  static async Task WorkAsync(CancellationToken ct)
  {
    // Poll occasionally; throw to end cooperatively
    for (int i = 0; i < 5; i++)
    {
      ct.ThrowIfCancellationRequested();
      Console.WriteLine("Step " + i);
      await Task.Delay(100, ct); // pass token to async API
    }
  }

  public static void Main(string[] args)
  {
    var cts = new CancellationTokenSource();
    Task t = WorkAsync(cts.Token);

    // Cancel after a short delay (simulated user action)
    Thread.Sleep(180);
    cts.Cancel();

    try
    {
      t.GetAwaiter().GetResult();
    }
    catch (OperationCanceledException)
    {
      Console.WriteLine("Canceled!");
    }
  }
}

转发令牌

通过每一层异步调用转发令牌,以便内部调用能够及时停止。

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

public class Program
{
  static async Task<string> FetchAsync(CancellationToken ct)
  {
    await Task.Delay(80, ct); // pretend I/O
    ct.ThrowIfCancellationRequested();
    return "data";
  }

  static async Task<string> ProcessAsync(CancellationToken ct)
  {
    string raw = await FetchAsync(ct); // forward token
    await Task.Delay(80, ct);
    return raw.ToUpperInvariant();
  }

  public static void Main(string[] args)
  {
    var cts = new CancellationTokenSource();
    Task<string> job = ProcessAsync(cts.Token);
    cts.CancelAfter(100); // schedule a cancellation
    try
    {
      Console.WriteLine(job.GetAwaiter().GetResult());
    }
    catch (OperationCanceledException)
    {
      Console.WriteLine("Pipeline canceled");
    }
  }
}

令牌.Register 清理

使用 令牌.Register 附加一个小型清理操作,在请求取消时运行。

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

public class Program
{
  static async Task UseRegistrationAsync(CancellationToken ct)
  {
    using (ct.Register(() => Console.WriteLine("Cleanup: releasing temp resources")))
    {
      for (int i = 0; i < 3; i++)
      {
        ct.ThrowIfCancellationRequested();
        await Task.Delay(120, ct);
        Console.WriteLine("Tick " + i);
      }
    }
  }

  public static void Main(string[] args)
  {
    var cts = new CancellationTokenSource();
    Task t = UseRegistrationAsync(cts.Token);
    Thread.Sleep(150);
    cts.Cancel();
    try { t.GetAwaiter().GetResult(); }
    catch (OperationCanceledException) { Console.WriteLine("Canceled with cleanup"); }
  }
}

链接源

CreateLinkedTokenSource 会将多个信号(例如用户取消和超时)合并为一个令牌。

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

public class Program
{
  static async Task WorkAsync(CancellationToken ct)
  {
    await Task.Delay(500, ct);
    Console.WriteLine("Finished work");
  }

  public static void Main(string[] args)
  {
    var parent = new CancellationTokenSource();
    var timeout = new CancellationTokenSource();
    timeout.CancelAfter(200);

    // Link both sources: cancel if parent OR timeout requests
    var linked = CancellationTokenSource.CreateLinkedTokenSource(parent.Token, timeout.Token);

    Task t = WorkAsync(linked.Token);
    try { t.GetAwaiter().GetResult(); }
    catch (OperationCanceledException) { Console.WriteLine("Canceled by parent/timeout"); }
    finally { linked.Dispose(); parent.Dispose(); timeout.Dispose(); }
  }
}

最佳实践

提示:

  • 将令牌传递给异步 API(Task.Delay、I/O),以便它们及时停止。
  • 抛出 OperationCanceledException 来结束工作;不要吞掉此异常。
  • 如果 CancellationTokenSource 持有计时器或注册项,请将其释放。
  • 保持处理程序快速;在 Register 中只执行最少的工作。

协作式取消规则

快速检查:方法响应取消请求的正确方式是什么?

回顾

回顾:让取消采用协作方式——传递令牌,进行轮询或调用 ThrowIfCancellationRequested,附加小型清理操作,并链接源以组合多个信号。

常见问题解答

「CancellationToken 模式与协作式取消」课时是免费的吗?

是的 — 「CancellationToken 模式与协作式取消」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 3 节课。

「CancellationToken 模式与协作式取消」这节课中我会学到什么?

传递并遵守 CancellationToken:创建 CTS,轮询取消状态或因取消而抛出异常,将其传给异步 API,并通过注册进行清理。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 3 节。

「CancellationToken 模式与协作式取消」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. CancellationToken 模式与协作式取消
  2. 超时、IProgress 与异步可释放对象(模拟)
  3. 弹性基础:重试与退避
← 返回 C# Academy