C# 中使用 CancellationTokenSource 优雅停止线程

半杯拿铁
半杯拿铁
发布时间:2026-10-13| 4人浏览过
原创

C# 开发中,如何安全、优雅地停止正在运行的线程是一个常见需求。传统的 Thread.Abort 方法已被弃用且危险,推荐使用 CancellationTokenSource 配合取消令牌来实现信号传递,确保线程能够检查自身状态并正常退出。

使用 CancellationTokenSource 停止线程

在 C# (.NET) 中,处理长周期后台任务(如持续运行的工作线程)的最佳实践是使用 CancellationToken。这种方法遵循“协作式取消”原则:被取消的任务需要定期检查令牌的状态,以便在不丢失资源锁或破坏数据一致性的情况下结束执行。

第1步:准备取消源与线程实例

首先,需要定义一个全局或成员级的 CancellationTokenSource 对象来管理取消请求。同时准备好要执行的线程数组。

  • 核心变量:
    • CancellationTokenSource cancel:用于触发和传递取消信号。
    • Thread[] thread:用于存放创建的线程实例,以便后续查询状态。
namespace WinFormApp
{
    public partial class Form1 : Form
    {
        // 1. 创建取消令牌源
        System.Threading.CancellationTokenSource cancel = new System.Threading.CancellationTokenSource();
        
        // 定义线程池数组
        System.Threading.Thread[] thread;
        int len = 2; // 线程数量

        public Form1()
        {
            InitializeComponent();
            thread = new System.Threading.Thread[len];
        }
    }
}

第2步:启动并监控线程

在线程的入口方法(如 Sample)中,设置一个 `while` 循环。在每次循环迭代中,检查 cancel.Token.IsCancellationRequested 的值。如果为 true,则执行清理逻辑并跳出循环,使线程自然结束。

  • 关键判断: if (cancel.IsCancellationRequested)
  • 回调注册: 可以在取消时调用 Token.Register() 绑定特定的清理函数。
void Sample()
{
    string name = System.Threading.Thread.CurrentThread.Name;
    ThreadInvoke.SetEventInvokeValue(richTextBox1, "正在运行线程:" + name);
    
    while (true)
    {
        // 检查是否收到取消信号
        if (cancel.IsCancellationRequested)
        {
            ThreadInvoke.SetEventInvokeValue(richTextBox1, "线程:" + name + " 停止运行...");
            
            // 可选:当取消发生时执行的特定回调
            cancel.Token.Register(delegate
            {
                ThreadInvoke.SetEventInvokeValue(richTextBox1, "线程:" + name + " 停止运行之后的回调函数...");
            });
            
            break; // 正常退出循环,线程安全结束
        }
    }
}

void RunThread()
{
    ThreadInvoke.SetEventInvokeValue(richTextBox1, "即将开始运行线程.");
    System.Threading.Thread t = null;
    for (int i = 0; i < len; i++)
    {
        t = new System.Threading.Thread(new System.Threading.ThreadStart(Sample));
        t.Name = "thread_0" + i.ToString();
        t.IsBackground = true; // 设为后台线程,程序退出时会自动终止
        thread.SetValue(t, i);
        t.Start();
    }
}

第3步:发送取消请求与验证结果

在主线程中(例如点击按钮时),调用 cancel.Cancel() 即可向所有使用该令牌的组件发出停止信号。随后可以通过遍历 IsAlive 属性确认线程是否已完全退出。

// 触发线程停止
private void button3_Click(object sender, EventArgs e)
{
    cancel.Cancel();
}

// 验证当前运行中的线程状态
void ShowStatu()
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < len; i++)
    {
        if (thread[i].IsAlive == true)
        {
            sb.AppendLine("线程:" + thread[i].Name.ToString() + " 还在运行...");
        }
    }
    if (sb.ToString() == "")
    {
        sb.AppendLine("线程已经全部停止...");
    }
    richTextBox1.Text += sb.ToString();
}

注意事项

注意: CancellationTokenSource 仅负责发送信号,线程是否能立刻响应取决于开发者在循环中是否主动检查了该信号。如果在等待阻塞操作中(如 Task.Wait 或网络读取),应传入对应的 CancellationToken 参数以实现更快的响应。

以上就是 C# 使用 CancellationTokenSource 优雅停止线程的详细内容,更多关于 C# 线程管理与异步操作优化的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。