C# 中使用 CancellationTokenSource 优雅停止线程
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# 线程管理与异步操作优化的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













