如何停止正在运行中的子线程
- 通过协作式取消模式
- 强制终止线程(可能存在资源不能及时释放的泄漏风险)
通过协作式取消模式
在线程函数中,你可以周期性地检查一个标志位,以确定是否应该停止线程。该标记位可以是共享变量,也可以是CancellationToken。
CancellationTokenSource 和 CancellationToken 被用来发送取消请求,而任务或线程通过检查 CancellationToken.IsCancellationRequested 属性或调用 ThrowIfCancellationRequested 方法来响应这个请求。
using System;
using System.Threading;
using System.Threading.Tasks; //
// 方式1:使用CancellationToken,停止标志位来停止线程
//
class CancellationTokenExample
{ private CancellationTokenSource _cts = new CancellationTokenSource(); public void StartWork() { Task.Run(() => { try { // 模拟长时间运行的工作,直到有取消请求时,退出while while(!_cts.IsCancellationRequested) { Thread.Sleep(1000); //如果有取消请求,也可以通过抛出异常结束线程_cts.Token.ThrowIfCancellationRequested();} } catch (OperationCanceledException) { //线程被取消 } }, _cts.Token); } // 调用此函数来停止线程public void StopWork() { _cts.Cancel(); }
}//
// 方式2:使用共享变量,停止标志位来停止线程
//
class ThreadStopExample
{ // 停止标志 public volatile bool StopRequested { get; set; } public void StartWork() { Task.Run(() => { while (!StopRequested) { Thread.Sleep(1000); // 模拟工作 } }); } // 调用此函数来停止线程public void StopWork() { StopRequested = true; }
}
强制终止线程(可能存在资源不能及时释放的泄漏风险)
如果在线程中使用了一个内层的无限循环(while (true)),这将导致线程永远不会退出这个内层循环,此时要退出线程,除非执行强制停止。
using System;
using System.Threading;
using System.Threading.Tasks; class ForceExitCaseExample
{private CancellationTokenSource _cts;private Task task;public void StartWork(){//确保线程没有重复运行if (task == null || (task.IsCompleted || task.IsCanceled)){_cts = new CancellationTokenSource();task = Task.Run(() =>{//注册cancel时,执行Abort方法(不太行,偶尔报异常)//_cts.Token.Register(Thread.CurrentThread.Abort);//注册cancel时,执行Interrupt方法_cts.Token.Register(Thread.CurrentThread.Interrupt);try{bool workDone = false;//模拟长时间运行的工作Thread.Sleep(1000);Console.WriteLine("第一阶段工作完成...");//模拟条件长时间不满足,运行工作死循环while (!workDone){Console.WriteLine("第二阶段工作中...");Thread.Sleep(999);if (false){workDone = true;}}}catch (Exception ex){//线程被取消 Console.WriteLine($"线程异常结束:{ex.Message}");}}, _cts.Token);}}// 调用此函数来停止线程public void StopWork(){_cts.Cancel();}
}