这个专题,是我学习的第一个,感觉还只是皮毛,没有深入,下次有时间一定再仔细琢磨一番!
多 线 程
多线程,通俗的理解,就是系统同时进行几件事情;这几件事情是并行的;
首先,这几件事没有先后次序之分;
进程所指包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
上面提到了Background状态表示该线程在后台运行,那么后台运行的线程有什么特别的地方呢?其实后台线程跟前台线程只有一个区别,那就是后台线程不妨碍程序的终止。一旦一个进程所有的前台线程都终止后,CLR(通用语言运行环境)将通过调用任意一个存活中的后台进程的Abort()方法来彻底终止进程。
后台线程:
前台线程:
.Net的公用语言运行时(CLR)能区分两种不同类型的线程:前台线程和后台线程。
这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
.Net的公用语言运行时(Common Language Runtime,CLR)能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
.net环境使用Thread建立的线程默认情况下是前台线程,即线程属性IsBackground=true,在进程中,只要有一个前台线程未退出,进程就不会终止。主线程就是一个前台线程。而后台线程不管线程是否结束,只要所有的前台线程都退出(包括正常退出和异常退出)后,进程就会自动终止。一般后台线程用于处理时间较短的任务,如在一个Web服务器中可以利用后台线程来处理客户端发过来的请求信息。而前台线程一般用于处理需要长时间等待的任务,如在Web服务器中的监听客户端请求的程序,或是定时对某些系统资源进行扫描的程序。下面的代码演示了前台和后台线程的区别。
public static void myStaticThreadMethod()
{
Thread.Sleep(3000);
}
Thread thread = new Thread(myStaticThreadMethod);
// thread.IsBackground = true;
thread.Start()
如果运行上面的代码,程序会等待3秒后退出,如果将注释去掉,将thread设成后台线程,则程序会立即退出
要注意的是,必须在调用Start方法之前设置线程的类型,否则一但线程运行,将无法改变其类型
通过BeginXXX方法运行的线程都是后台线程
老实说,我懂了,但是不知道该怎么用?!
几个事件:
1,启动线程:start()
判断是否仍在运行
if(oThread.IsAlive)
{
//该线程仍在运行
}
else
{
执行完,已结束
}
2,前台线程,后台线程(老实说,没弄明白,照搬吧)
理解;前台线程是一个进程的基本线程,
后台线程:在后台工作的线程或应用程序结束后没有必要再存在下去的线程应该是后台线程。比如,如果应用程序启动一个执行冗长计算的线程,把它设置为后台线程可以使应用程序在关闭前不必显示停止该线程。
3,线程优先级
ThreadPriority.Highest
ThreadPriority.AboveNormal
ThreadPriority.Normal
ThreadPriority.BelowNormal
ThreadPriority.Lowest
线程优先级是和主进程内所有线程都有关系,而不只是应用程序域里的其它线程,因此,应该慎重设置线程的优先级。
主进程:
应用程序域:一种边界,它由公共语言运行库围绕同一应用程序范围内创建的对象建立。应用程序域有助于将在一个应用程序中创建的对象与在其他应用程序中创建的对象隔离,以使运行时行为可以预知。在一个单独的进程中可以存在多个应用程序域。
4,挂起和恢复线程
挂起:suspend(),一个线程可以挂起自己或他人,无论多少次suspend(),一次resume()就能让它恢复运行
休息:sleep(),一个线程只能对自身调用sleep。Thread.Sleep(5000);
5,终止线程
在Windows API中,不提供一个线程清晰的中止另一个线程的可靠方法,如果线程A想终止线程B,通常给线程B发信号让B终止自己
在托管代码中,一个线程可以清晰的中止另一个线程。
thread.Abort(); CLR监督托管代码的执行,在目标线程中引发ThreadAbortException异常,使线程结束。
Abort能顺利的终止一个托管代码,但要是线程跑到托管代码以外,则CLR也没有办法。
线程可以用ResetAbort()方法使自己不被终止。那么终止与反终止,谁先谁后呢?
try
{
}
catch(ThreadAbortException)
{
Thread.ResetAbort();
}
在catch处理结束后,CLR引发一个ThreadAbortException异常,有效终止线程。但catch块里的resetAbort阻止自己被终止。
在实践中,终止另一线程的线程经常会暂停,直到另一线程结束。
Thread.join派上用场。
thread.Abort();//让其它线程终止
thread.Join();//在线程终止之前暂停 thread.Join(5000);
托管代码;
由公共语言运行库环境(而不是直接由操作系统)执行的代码。托管代码应用程序可以获得公共语言运行库服务,例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。
托管代码是可以使用20多种支持Microsoft .NET Framework的高级语言编写的代码,它们包括:C#, J#, Microsoft Visual Basic .NET, Microsoft JScript .NET, 以及C++。所有的语言共享统一的类库集合,并能被编码成为中间语言(IL)。运行库编译器(runtime-aware ompiler)在托管执行环境下编译中间语言(IL)使之成为本地可执行的代码,并使用数组边界和索引检查,异常处理,垃圾回收等手段确保类型的安全。
在托管执行环境中使用托管代码及其编译,可以避免许多典型的导致安全黑洞和不稳定程序的编程错误。同样,许多不可靠的设计也自动的被增强了安全性,例如 类型安全检查,内存管理和释放无效对象。程序员可以花更多的精力关注程序的应用逻辑设计并可以减少代码的编写量。这就意味着更短的开发时间和更健壮的程序。
托管代码收.NET的运行时来运行
非托管代码直接收CPU执行
最保险的方法:ManualResetEvent
ManualResetEvent,依据我的理解,是对线程进行控制,控制他的起始和结束等,如下面例子:
设想我们不想在一开始新线程就让它马上运行结束,也就是说,我们开启了一个新线程,让它运行,在某个特定的时间点,新线程暂停并等待从主线程(或其他线程)发来的消息。
我们可以这样定义:
public static ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。注意,为了通知或监听同一个线程,所有的其它线程都能访问那个类。
等待线程这样写:
mre.WaitOne();
这将引起等待线程无限期的阻塞并等待类来通知。
发信号的线程应该这样:
mre.Set();
这样类就会被通知,值变成true,等待线程就会停止等待。在通知事件发生后,我们就可以使用下面语句把线程置于基状态:
mre.Reset();
现在让我们在程序执行一下:





















































