[C# 线程处理系列]专题二:线程的详细使用
2013-05-29 21:26
531 查看
一、上节补充
对于Thread类还有几个常用方法需要说明的。
1.1 Suspend和Resume方法
这两个方法在.net Framework 1.0的时候就支持的方法,他们分别可以挂起线程和恢复挂起的线程。但在.net Framework 2.0以后的版本中这两个方法都过时了,MSDN的解释是这样:
警告:
不要使用 Suspend 和 Resume 方法来同步线程的活动。您无法知道挂起线程时它正在执行什么代码。如果您在安全权限评估期间挂起持有锁的线程,则
AppDomain中的其他线程可能被阻止。如果您在线程正在执行类构造函数时挂起它,则 AppDomain中尝试使用该类的其他线程将被阻止。这样很容易发生死锁。
对于这个解释可能有点抽象吧,让我们来看看一段代码可能会清晰点:
在上面这段代码中thread1线程是在主线程中恢复的,但当主线程发生异常时,这时候就thread1一直处于挂起状态,此时thread1所使用的资源就不能释放(除非强制终止进程),当另外线程需要使用这快资源的时候, 这时候就很可能发生死锁现象。
上面一段代码还存在一个隐患,请看下面一小段代码:
当主线程跑(运行)的太快,做完自己的事情去唤醒thread1时,此时thread1还没有挂起而起唤醒thread1,此时就会出现异常了。并且上面使用的Suspend和Resume方法,编译器已经出现警告了,提示这两个方法已经过时, 所以在我们平时使用中应该尽量避免。
1.2 Abort和 Interrupt方法
Abort方法和Interrupt都是用来终止线程的,但是两者还是有区别的。
1、他们抛出的异常不一样,Abort 方法抛出的异常是ThreadAbortException, Interrupt抛出的异常为ThreadInterruptedException
2、调用interrupt方法的线程之后可以被唤醒,然而调用Abort方法的线程就直接被终止不能被唤醒的。
下面一段代码是掩饰Abort方法的使用
运行结果:
从运行结果可以看出,调用Abort方法的线程引发的异常类型为ThreadAbortException, 以及异常只会在 调用Abort方法的线程中发生,而不会在主线程中抛出,并且调用Abort方法后线程的状态不是立即改变为Aborted状态,而是从AbortRequested->Aborted。
Interrupt方法:
运行结果:
从结果中可以得到,调用Interrupt方法抛出的异常为:ThreadInterruptException, 以及当调用Interrupt方法后线程的状态应该是中断的, 但是从运行结果看此时的线程因为了Join,Sleep方法而唤醒了线程,为了进一步解释调用Interrupt方法的线程可以被唤醒, 我们可以在线程执行的方法中运用循环,如果线程可以唤醒,则输出结果中就一定会有循环的部分,然而调用Abort方法线程就直接终止,就不会有循环的部分,下面代码相信大家看后肯定会更加理解两个方法的区别的:
运行结果为:
如果把上面的 thread1.Interrupt();改为 thread1.Abort(); 运行结果为:
对于Thread类还有几个常用方法需要说明的。
1.1 Suspend和Resume方法
这两个方法在.net Framework 1.0的时候就支持的方法,他们分别可以挂起线程和恢复挂起的线程。但在.net Framework 2.0以后的版本中这两个方法都过时了,MSDN的解释是这样:
警告:
不要使用 Suspend 和 Resume 方法来同步线程的活动。您无法知道挂起线程时它正在执行什么代码。如果您在安全权限评估期间挂起持有锁的线程,则
AppDomain中的其他线程可能被阻止。如果您在线程正在执行类构造函数时挂起它,则 AppDomain中尝试使用该类的其他线程将被阻止。这样很容易发生死锁。
对于这个解释可能有点抽象吧,让我们来看看一段代码可能会清晰点:
class Program { static void Main(string[] args) { // 创建一个线程来测试 Thread thread1 = new Thread(TestMethod); thread1.Name = "Thread1"; thread1.Start(); Thread.Sleep(2000); Console.WriteLine("Main Thread is running"); ////int b = 0; ////int a = 3 / b; ////Console.WriteLine(a); thread1.Resume(); Console.Read(); } private static void TestMethod() { Console.WriteLine("Thread: {0} has been suspended!", Thread.CurrentThread.Name); //将当前线程挂起 Thread.CurrentThread.Suspend(); Console.WriteLine("Thread: {0} has been resumed!", Thread.CurrentThread.Name); } }
在上面这段代码中thread1线程是在主线程中恢复的,但当主线程发生异常时,这时候就thread1一直处于挂起状态,此时thread1所使用的资源就不能释放(除非强制终止进程),当另外线程需要使用这快资源的时候, 这时候就很可能发生死锁现象。
上面一段代码还存在一个隐患,请看下面一小段代码:
class Program { static void Main(string[] args) { // 创建一个线程来测试 Thread thread1 = new Thread(TestMethod); thread1.Name = "Thread1"; thread1.Start(); Console.WriteLine("Main Thread is running"); thread1.Resume(); Console.Read(); } private static void TestMethod() { Console.WriteLine("Thread: {0} has been suspended!", Thread.CurrentThread.Name); Thread.Sleep(1000); //将当前线程挂起 Thread.CurrentThread.Suspend(); Console.WriteLine("Thread: {0} has been resumed!", Thread.CurrentThread.Name); } }
当主线程跑(运行)的太快,做完自己的事情去唤醒thread1时,此时thread1还没有挂起而起唤醒thread1,此时就会出现异常了。并且上面使用的Suspend和Resume方法,编译器已经出现警告了,提示这两个方法已经过时, 所以在我们平时使用中应该尽量避免。
1.2 Abort和 Interrupt方法
Abort方法和Interrupt都是用来终止线程的,但是两者还是有区别的。
1、他们抛出的异常不一样,Abort 方法抛出的异常是ThreadAbortException, Interrupt抛出的异常为ThreadInterruptedException
2、调用interrupt方法的线程之后可以被唤醒,然而调用Abort方法的线程就直接被终止不能被唤醒的。
下面一段代码是掩饰Abort方法的使用
using System; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Thread abortThread = new Thread(AbortMethod); abortThread.Name = "Abort Thread"; abortThread.Start(); Thread.Sleep(1000); try { abortThread.Abort(); } catch { Console.WriteLine("{0} Exception happen in Main Thread", Thread.CurrentThread.Name); Console.WriteLine("{0} Status is:{1} In Main Thread ", Thread.CurrentThread.Name, Thread.CurrentThread.ThreadState); } finally { Console.WriteLine("{0} Status is:{1} In Main Thread ", abortThread.Name, abortThread.ThreadState); } abortThread.Join(); Console.WriteLine("{0} Status is:{1} ", abortThread.Name, abortThread.ThreadState); Console.Read(); } private static void AbortMethod() { try { Thread.Sleep(5000); } catch(Exception e) { Console.WriteLine(e.GetType().Name); Console.WriteLine("{0} Exception happen In Abort Thread", Thread.CurrentThread.Name); Console.WriteLine("{0} Status is:{1} In Abort Thread ", Thread.CurrentThread.Name, Thread.CurrentThread.ThreadState); } finally { Console.WriteLine("{0} Status is:{1} In Abort Thread", Thread.CurrentThread.Name, Thread.CurrentThread.ThreadState); } } }
运行结果:
从运行结果可以看出,调用Abort方法的线程引发的异常类型为ThreadAbortException, 以及异常只会在 调用Abort方法的线程中发生,而不会在主线程中抛出,并且调用Abort方法后线程的状态不是立即改变为Aborted状态,而是从AbortRequested->Aborted。
Interrupt方法:
using System; using System.Threading; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Thread interruptThread = new Thread(AbortMethod); interruptThread.Name = "Interrupt Thread"; interruptThread.Start(); interruptThread.Interrupt(); interruptThread.Join(); Console.WriteLine("{0} Status is:{1} ", interruptThread.Name, interruptThread.ThreadState); Console.Read(); } private static void AbortMethod() { try { Thread.Sleep(5000); } catch(Exception e) { Console.WriteLine(e.GetType().Name); Console.WriteLine("{0} Exception happen In Interrupt Thread", Thread.CurrentThread.Name); Console.WriteLine("{0} Status is:{1} In Interrupt Thread ", Thread.CurrentThread.Name, Thread.CurrentThread.ThreadState); } finally { Console.WriteLine("{0} Status is:{1} In Interrupt Thread", Thread.CurrentThread.Name, Thread.CurrentThread.ThreadState); } } } }
运行结果:
从结果中可以得到,调用Interrupt方法抛出的异常为:ThreadInterruptException, 以及当调用Interrupt方法后线程的状态应该是中断的, 但是从运行结果看此时的线程因为了Join,Sleep方法而唤醒了线程,为了进一步解释调用Interrupt方法的线程可以被唤醒, 我们可以在线程执行的方法中运用循环,如果线程可以唤醒,则输出结果中就一定会有循环的部分,然而调用Abort方法线程就直接终止,就不会有循环的部分,下面代码相信大家看后肯定会更加理解两个方法的区别的:
using System; using System.Threading; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { Thread thread1 = new Thread(TestMethod); thread1.Start(); Thread.Sleep(100); thread1.Interrupt(); Thread.Sleep(3000); Console.WriteLine("after finnally block, the Thread1 status is:{0}", thread1.ThreadState); Console.Read(); } private static void TestMethod() { for (int i = 0; i < 4; i++) { try { Thread.Sleep(2000); Console.WriteLine("Thread is Running"); } catch (Exception e) { if (e != null) { Console.WriteLine("Exception {0} throw ", e.GetType().Name); } } finally { Console.WriteLine("Current Thread status is:{0} ", Thread.CurrentThread.ThreadState); } } } } }
运行结果为:
如果把上面的 thread1.Interrupt();改为 thread1.Abort(); 运行结果为:
相关文章推荐
- [C# 线程处理系列]专题三:线程池中的工作者线程
- [C# 线程处理系列]专题一:线程基础
- [C# 线程处理系列]专题一:线程基础
- [C# 线程处理系列]专题四:线程同步
- [C# 线程处理系列]专题三:线程池中的工作者线程
- [C# 线程处理系列]专题二:线程池中的工作者线程
- [C# 线程处理系列]专题六:线程同步——信号量和互斥体
- [C# 线程处理系列]专题五:线程同步
- [C# 线程处理系列]专题四:线程池中的I/O线程
- [C# 线程处理系列]专题五:线程同步——事件构造
- [C# 线程处理系列]专题一:线程基础
- [C# 线程处理系列]专题六:线程同步——事件构造
- [C# 线程处理系列]专题七:线程同步——信号量和互斥体
- [C# 线程处理系列]专题三:线程池中的I/O线程
- Android 系列 4.11使用活动线程队列和处理程序在线程之间发送消息
- [.Net 线程处理系列]专题一:线程基础
- C#线程处理系列之线程池中的I/O线程
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
- C# 字符串处理的详细使用(转)
- C#跨线程操作控件 通过委托处理,MSDN上又很详细用法的说明