[C#基础]线程学习笔记(二)
2015-06-03 08:06
716 查看
参考链接:
http://blog.csdn.net/jasonvip_c/article/details/5718636 http://www.cnblogs.com/miniwiki/archive/2010/06/18/1760540.html
1.前台线程与后台线程
Net的公用语言运行时(Common Language Runtime,CLR)能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
一个线程是前台线程还是后台线程可由它的IsBackground属性来决定。这个属性是可读又可写的。它的默认值为false,即意味着一个线程默认为前台线程。我们可以将它的IsBackground属性设置为true,从而使之成为一个后台线程。
示例:
既然前台线程和后台线程有这种差别,那么我们怎么知道该如何设置一个线程的IsBackground属性呢?下面是一些基本的原则:对于一些在后台运行的线程,当程序结束时这些线程没有必要继续运行了,那么这些线程就应该设置为后台线程。比如一个程序启动了一个进行大量运算的线程,可是只要程序一旦结束,那个线程就失去了继续存在的意义,那么那个线程就该是作为后台线程的。而对于一些服务于用户界面的线程往往是要设置为前台线程的,因为即使程序的主线程结束了,其他的用户界面的线程很可能要继续存在来显示相关的信息,所以不能立即终止它们。这里我只是给出了一些原则,具体到实际的运用往往需要编程者的进一步仔细斟酌。
2.线程与进程
一个不错的解释:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
简单地说,就是:
一个系统可以执行多个进程,允许多个任务同时运行
一个进程可以执行多个线程,允许任务分成不同的部分运行
一个进程的内存空间是共享的,每个线程都可以使用这些共享内存
3.何时使用多线程
多线程程序一般被用来在后台执行耗时的任务。主线程保持运行,并且工作线程做它的后台工作。对于Windows Forms程序来说,如果主线程试图执行冗长的操作,键盘和鼠标的操作会变的迟钝,程序也会失去响应。由于这个原因,应该在工作线程中运行一个耗时任务时添加一个工作线程,即使在主线程上有一个有好的提示“处理中...”,以防止工作无法继续。这就避免了程序出现由操作系统提示的“没有相应”,来诱使用户强制结束程序的进程而导致错误。
4.何时不使用多线程
多线程也同样会带来缺点,最大的问题是它使程序变的过于复杂,拥有多线程本身并不复杂,复杂是的线程的交互作用,这带来了无论是否交互是否是有意的,都会带来较长的开发周期,以及带来间歇性和非重复性的bugs。因此,要么多线程的交互设计简单一些,要么就根本不使用多线程。除非你有强烈的重写和调试欲望。
当用户频繁地分配和切换线程时,多线程会带来增加资源和CPU的开销。
5.线程优先级
有五种取值,按优先级从高到低为:
Highest > AboveNormal > Normal Below > Normal > Lowest
默认情况下,线程具有Normal 优先级。
运行结果:
6.异常处理
这里try/catch语句一点用也没有,新创建的线程会引发NullReferenceException异常
正确的捕获异常的方法是:
http://blog.csdn.net/jasonvip_c/article/details/5718636 http://www.cnblogs.com/miniwiki/archive/2010/06/18/1760540.html
1.前台线程与后台线程
Net的公用语言运行时(Common Language Runtime,CLR)能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
一个线程是前台线程还是后台线程可由它的IsBackground属性来决定。这个属性是可读又可写的。它的默认值为false,即意味着一个线程默认为前台线程。我们可以将它的IsBackground属性设置为true,从而使之成为一个后台线程。
示例:
using System; using System.Threading; class ThreadTest11 { static void Main(string[] args) { for (int i = 0; i < 10; i++) { Thread t = new Thread(Go); //若添加这句话,则创建完十个线程之后就会退出控制台程序 //若注释这句话,则等待五秒后就会退出控制台程序 //t.IsBackground = true; t.Start(); } } static void Go() { DateTime start = DateTime.Now; while ((DateTime.Now - start).Seconds < 5) ; } }
既然前台线程和后台线程有这种差别,那么我们怎么知道该如何设置一个线程的IsBackground属性呢?下面是一些基本的原则:对于一些在后台运行的线程,当程序结束时这些线程没有必要继续运行了,那么这些线程就应该设置为后台线程。比如一个程序启动了一个进行大量运算的线程,可是只要程序一旦结束,那个线程就失去了继续存在的意义,那么那个线程就该是作为后台线程的。而对于一些服务于用户界面的线程往往是要设置为前台线程的,因为即使程序的主线程结束了,其他的用户界面的线程很可能要继续存在来显示相关的信息,所以不能立即终止它们。这里我只是给出了一些原则,具体到实际的运用往往需要编程者的进一步仔细斟酌。
2.线程与进程
一个不错的解释:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
简单地说,就是:
一个系统可以执行多个进程,允许多个任务同时运行
一个进程可以执行多个线程,允许任务分成不同的部分运行
一个进程的内存空间是共享的,每个线程都可以使用这些共享内存
3.何时使用多线程
多线程程序一般被用来在后台执行耗时的任务。主线程保持运行,并且工作线程做它的后台工作。对于Windows Forms程序来说,如果主线程试图执行冗长的操作,键盘和鼠标的操作会变的迟钝,程序也会失去响应。由于这个原因,应该在工作线程中运行一个耗时任务时添加一个工作线程,即使在主线程上有一个有好的提示“处理中...”,以防止工作无法继续。这就避免了程序出现由操作系统提示的“没有相应”,来诱使用户强制结束程序的进程而导致错误。
4.何时不使用多线程
多线程也同样会带来缺点,最大的问题是它使程序变的过于复杂,拥有多线程本身并不复杂,复杂是的线程的交互作用,这带来了无论是否交互是否是有意的,都会带来较长的开发周期,以及带来间歇性和非重复性的bugs。因此,要么多线程的交互设计简单一些,要么就根本不使用多线程。除非你有强烈的重写和调试欲望。
当用户频繁地分配和切换线程时,多线程会带来增加资源和CPU的开销。
5.线程优先级
public enum ThreadPriority
有五种取值,按优先级从高到低为:
Highest > AboveNormal > Normal Below > Normal > Lowest
默认情况下,线程具有Normal 优先级。
using System; using System.Threading; class ThreadTest12 { static void Main() { PriorityTest priorityTest = new PriorityTest(); ThreadStart startDelegate = new ThreadStart(priorityTest.ThreadMethod); Thread threadOne = new Thread(startDelegate); threadOne.Name = "ThreadOne"; Thread threadTwo = new Thread(startDelegate); threadTwo.Name = "ThreadTwo"; threadTwo.Priority = ThreadPriority.BelowNormal; threadOne.Start(); threadTwo.Start(); // Allow counting for 3 seconds. Thread.Sleep(3000); priorityTest.LoopSwitch = false; Console.Read(); } } class PriorityTest { bool loopSwitch; public PriorityTest() { loopSwitch = true; } public bool LoopSwitch { set { loopSwitch = value; } } public void ThreadMethod() { long threadCount = 0; while (loopSwitch) { threadCount++; } Console.WriteLine("{0} with {1,11} priority " + "has a count = {2,13}", Thread.CurrentThread.Name, Thread.CurrentThread.Priority.ToString(), threadCount.ToString("N0")); } }
运行结果:
6.异常处理
using System; using System.Threading; class ThreadTest13 { static void Main(string[] args) { try { new Thread(Go).Start(); } catch (Exception ex) { Console.WriteLine("Exception"); } } static void Go() { throw null; } }
这里try/catch语句一点用也没有,新创建的线程会引发NullReferenceException异常
正确的捕获异常的方法是:
using System; using System.Threading; class ThreadTest13 { static void Main(string[] args) { new Thread(Go).Start(); } static void Go() { try { throw null; } catch (Exception ex) { Console.WriteLine("Exception"); Console.Read(); } } }
相关文章推荐
- Excel数据导入(C#)
- c# 中将一个方法的名称作为另一个方法的参数
- Part 72 to 81 Talking about Dictionary and List collection in C#
- c#输出文件名、行号、函数名、列号
- C# ICSharpCode.SharpZipLib
- C#/.NET code
- C#代码小记
- C#中用后台代码实现向XML文档中追加内容
- [C#基础]线程学习笔记(一)
- 免费电子书:C#代码整洁之道
- Image Processing using C#
- C# Serializable
- C#后台代码创建XML文档
- C# LayoutKind
- C#中的using(){}
- c# 动态调用webservice 转录一下
- 寒風的C#之旅之面向对象的课后习题
- C# 文本框禁止复制粘贴、只能输入数字
- [深入学习C#]匿名函数、委托和Lambda表达式
- 【C#】利用反射机制创建对象