改善C#程序的157个建议(连载77)

发表于:2011-11-21 09:32

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:陆敏技    来源:51Testing软件测试网采编

  建议77:正确停止线程

  开发者总尝试对自己的代码有更多的控制。例如,“让那个还在工作的线程马上停止下来”。然而,并非我们想怎样就可以怎样的,这至少涉及两个问题。

  第一个问题 正如线程不能立即启动一样,线程也并不是说停就停的。无论采用何种方式通知工作线程需要停止,工作线程都会忙完手头最紧要的活,然后在它觉得合适的时候退出。以最传统的Thread.Abort方法为例,如果线程当前正在执行的是一段非托管代码,那么CLR就不会抛出ThreadAbortException,只有当代码继续回到CLR中时,才会引发ThreadAbortException。当然,即便是在CLR环境中,ThreadAbortException也不会立即引发。

  第二个问题 要正确停止线程,不在于调用者采取了什么行为(如最开始的Thread.Abort()方法),而更多依赖于工作线程是否能主动响应调用者的停止请求。大体机制是,如果线程需要被停止,那么线程自身就应该负责给调用者开放这样的接口:Cancled。线程在工作的同时,还要以某种频率检测Cancled标识,若检测到Cancled,线程自己才会负责退出。

  FCL现在为我们提供了标准的取消模式:协作式取消(Cooperative Cancellation)。协作式取消的机制就是上文第二个问题中所提到的机制。下面是一个最基础的协作式取消的示例:

  1. CancellationTokenSource cts = new CancellationTokenSource();  
  2. Thread t = new Thread(() => 
  3.     {  
  4.         while (true)  
  5.         {  
  6.             if (cts.Token.IsCancellationRequested)  
  7.             {  
  8.                 Console.WriteLine("线程被终止!");  
  9.                 break;  
  10.             }  
  11.             Console.WriteLine(DateTime.Now.ToString());  
  12.             Thread.Sleep(1000);  
  13.         }  
  14.     });  
  15. t.Start();  
  16. Console.ReadLine();  
  17. cts.Cancel();

  调用者使用CancellationTokenSource的Cancel方法通知工作线程退出。工作线程则以大约1000ms的频率一边工作,一边检查是否有外界传入的Cancel信号,若有这样的信号,则退出。可以看到,在正确停止线程的机制中,真正起到主要作用的是线程本身。示例中的工作代码比较简单,但足以说明问题。更复杂的计算式工作,也应该以这样的一种方式,妥善而正确地处理退出。

  协作式取消中的关键类型是CancellationTokenSource。它有一个关键属性Token,Token是一个名为CancellationToken的值类型。CancellationToken继而进一步提供了布尔值的属性IsCancellationRequested作为需要取消工作的标识。CancellationToken还有一个方法尤其值得注意,那就是Register方法。它负责传递一个Action委托,在线程停止的时候被回调,使用方法如下:

  1. cts.Token.Register(() => 
  2. {  
  3.     Console.WriteLine("工作线程被终止了。");  
  4. });

  本例使用Thread进行了演示,如果使用ThreadPool也是一样的模式,这里就不再赘述。后面还会讲到任务Task,它依赖于CancellationTokenSource和CancellationToken完成了所有的取消控制。

相关链接:

改善C#程序的157个建议(连载1)

改善C#程序的157个建议(连载2)

改善C#程序的157个建议(连载3)

改善C#程序的157个建议(连载4)

改善C#程序的157个建议(连载5)

改善C#程序的157个建议(连载6)

改善C#程序的157个建议(连载7)

改善C#程序的157个建议(连载8)

改善C#程序的157个建议(连载9)

改善C#程序的157个建议(连载10)

改善C#程序的157个建议(连载11)

改善C#程序的157个建议(连载12)

改善C#程序的157个建议(连载13)

改善C#程序的157个建议(连载14)

改善C#程序的157个建议(连载15)

改善C#程序的157个建议(连载71)

改善C#程序的157个建议(连载72)

改善C#程序的157个建议(连载73)

改善C#程序的157个建议(连载74)

改善C#程序的157个建议(连载75)

改善C#程序的157个建议(连载76)

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号