*摘要
。线程原理概述
。.NET下的多线程编程
。异步编程
。ASP.NET多线程编程
* 线程基本概念
。线程是程序执行的基本原子单位。一个进程可以由多个线程组成。
。每个线程都维护异常处理程序、调度优先和一组系统用于在调度该线程前保存线程上下文的结构。线程上下文包括为使线程在线程宿主进程地址空间中无缝地继续执行所需的所有信息,包括线程的CPU寄存器组和堆栈。
。在分布式编程中,正确使用线程能够很好的提高应用程序的性能及运行效率。实现原理是将一个进程分成多个线程,然后让它们并发异步执行,来提高运行效率。
。并发执行并不是同时执行(占有CPU),任意时刻还是只能有一个线程占用CPU,只不过是它们争夺CPU频繁一些,感觉到他们似乎都在运行。
* 什么时候用线程?
。一般情况下,如果多个线程在执行时都要抢占某一个资源或某几个资源,则最好不用异步线程执行。因为它们是并发执行,很可能同时争夺某个资
源有CPU,这时要么执行资源分配算法(比如要判断哪个线程优先级高,这要花费时间),或者是按时间片算法(这样要付出轮询CPU/交接/让出CPU
所需的时间)
。如果多个线程所需要的系统资源是比较均匀的,这时完全可以让它们异步并发执行。
* 使用线程的缺点
。统将为进程和线程所需的上下文信息使用内在。因此,可以创建的进程,AppDomain对象和线程的数目会受到可用内存的限制。
。跟踪大量的线程将占用大量的处理时间。如果线程过多,则其中大多数线程都不会产生明显的进度。如果大多数当前线程处于一个进程中,则其他
进程中的线程的调度频率就会很低。
。使用许多线程控制代码非常复杂,并可能产生许多错误。
。销毁线程需要了解可能发生的问题并对那些问题进行处理。
* .NET下的多线程编程
。Thread类的使用
。带参数线程
。委托与线程。
。应用程序域
。临界区操作。
* System.Threading
。提供一些使得可以进行多线程编程的类和接口。此命名空间包括管理线程组的ThreadPool类,使得可以在指定的时间后调用委托的Timer类以及用
于同步互斥线程的Mutex类。System.Threading还提供用于线程调度,等待通知死销解析的类。
。Using System.Threading;
* Thread类
。a.启动线程:即新建并启动一个线程:
-Tread Thead1=new Tread(new ThreadStart(Count));其中的Count是将要被新线程执行的函数。
。b.杀死线程
-在杀死一个线程前最好先判断它是否还活着(通过IsAlive属性),然后就可以调用Abort方法来杀死此线程。
。c.暂停线程
-即让一个正运行的线程休眠一段时间。如thread.Sleep(1000);就是让线程休眠1秒钟。
。d.优先级
-Thread类中ThreadPriority属性,它用来设置优先级,但不能保证操作系统会接受该优先级。一个线程的优先级可分5种:
Normal,AboveNormal,BelowNormal,Highest,Lowest.
。e.挂起线程
-Thread类的Suspend方法用来挂起线程。直到调用Resume,此线程才可以继续执行。如果线程已经挂起,那就不会起作用。
。f.恢复线程
-Resume方法用来恢复已经挂起的线程,以让它继续执行,如果线程没挂起,也不会起作用。
。一个线程的方法不包含任何参数,同时也不返回任何值。它的命名规则和一般函数的命名规则相同。它既可以是静态的(static)也可以是非静态
的(nonstatic)。当它执行完成后,相应的线程也就结束了,其线程对象的IsAlive属性敢就被置为false了。
。.NET的公用语言运行时(CLR)能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可
以退出;而对于后台线程,应用程序则可以不考虑程序退出时都会自动结束
。一个线程是前台线程还是后台线程可由它的IsBackground属性来决定。
* 带参数线程
。创建线程时,将使用采用ThreadStart委托作为其唯一参数的构造函数创建Thread类的新实例。但线程在调用Start方法前不会开始执行。调用“开
始”后,将从由ThreadStart委托引用的方法的第一行开始执行。
。当创建ThreadStart委托时,将标识处理事件的方法。若要使事件处理程序与事件关联,请将该委托的一个实例添加到事件。每当事件出现时就调
用事件处理程序,除非移除了该委托。
。线程还能够调用带参数的方法,即使ThreadStart委托只带一个参数——表示状态的对象。正是该对象应将参数传送给被调用方法。
* 委托与线程
1、委托基础
-委托使用的目标:把函数作为参数传递
-类似于C++中的函数指针
-是事件处理的基础
-函数指针只能引用静态函数,而委托可以引用静态方法和实例方法。当委托引用实例方法时,委托不仅存储对方法入口点的引用,还存储对为其调
用该方法的类实例的引用。
-委托声明:
。delegate double process(double db1);
。delegate 函数返回类型名 委托名 (函数参数)
* 委托使用实例
delegate void MyDelegate(int i); //委托声明
class Program
{
public static void Main()
{
TakesADelegate(new MyDelegate(DelegateFunction));
}
public static void TakesADelegate(MyDelegate SomeFunction){SomeFunction(21);}
public static void DelegateFunction(int i)
{System.Console.WriteLine("Called by delegate with number;{0}",i);}
}
* 应用程序域
。操作系统和运行库环境通常会在应用程序间提供某种形式的隔离。为确保在一个应用程序中运行的代码不会对其他不相关的应用程序产生不良影响
,这种隔离是必需的。
。.NET中新增了一个隔离层,称为应用程序域AppDomain,它是进行内部一个逻辑独立部分。
。应用程序域提供安全而通用的处理单元,公共语言运行库可使用它来提供应用程序之间的隔离。在一个应用程序中出现的错误不会影响其他应用程
序。
。使用应用程序域:
-能够在不停止整个进行的情况下停止单个应用程序。
-在一个应用程序中运行的代码不能直接访问其他应用程序中的代码或资源。
-代码行为的作用范围由它运行所在的应用程序决定。
-向代码授予的权限可以由代码运行所在的应用程序域来控制。
* 应用程序域和线程
。线和程是公共语言运行库用来执行代码的操作系统构造。在运行时,所有托管代码均加载到一个应用程序域中,由特定的操作系统线程来运行。
。应用程序域和线程之间不具有一对一的相关性。在任意给定时间,在单个应用程序域中可以执行几个线程,而且特定线程并不局限在单个应用程序
域内。也就是说,线程可以自由跨越应用程序域边界;不为每个应用程序域创建新线程。
。在任意给定时间,每一线程都在一个应用程序域中执行。运行库会跟踪在哪些应用程序域中有哪些线程正在运行。通过调用Thread.GetDomain方法
,您可以随时确定线程执行所在的域。
* 临界区操作
。Lock关键字:将某个语句块标记为临界区,另一个线程不进 入临界区。
。Interlocked类:为多个线程共享的变量提供原子操作。Increment和Decrement方法递增或递减变量并将结果值存储在单个操作中。
。Monitor类:提供同步对对象的访问的机制。
Monitor类通过向单个线程授予对象锁来控制对对象的访问。使用Enter和Exit方法标记临界区的开头和结尾。
* 异步委托
。异步委托提供以异步方式调用同步方法的能力。
。当同步调用一个委托时,调用方法直接对当前线程调用目标方法。如果编译器支持异步委托,则它将生成该调用方法以及BeginInvoke和EndInvoke
方法。
。如果调用BeginInvoke方法,则公共语言运行库将对请求进行排队并立即返回到调用方。将对来自线程池的线程调用该目标方法。提交请求的原始
线程自由地继续与目标方法并行执行,该目标方法是对线程池线程运行的。
。在回调中,使用EndInvoke方法来获取返回值和输入/输出参数。如果没有对BeginInvoke指定回调,则可以在提交请求的原始线程上使用EndInvoke
* ASP.NET中的线程处理
。为了有效地为多个客户端请求提供服务,Web服务器就要大量使用并发,这是通过启动多个进程以及/或者产生多个线程来为请求提供服务和执行工
作实现的。
。ASP.NET也不例外,它在每个辅助进行中使用多个线程来为请求提供服务。
。ASP.NET使用进程范围的CLR线程池为请求提供服务。该池的大小可以machine.config的processModel元素中进行配置,并且被默认设置为25个辅助
线程和25个I/O线程。
。对于每个到来的请求,对于该应用程序的关联模块也是如此。为了避免对于步繁地重新分配应用程序和模块,每个AppDomain都维护一个应用程序
和模块池。应用程序池的最大大小与线程池的大小相同,因此,默认请况下,每个辅助进程最多有25个请求可以进行并发处理,每个请求都具有它自
己的应用程序和模块集。
请发表评论