微软.NET
Framework的许多新花样中的一个就是它包含了一个容易而标准的创建自由线程应用程序的方法。因为在VB6里,没有外部的帮助代码,你就不能在一个应用程序里创建线程,所以这个语言功能对许多将要从事。NET开发的程序员来说是崭新的。在本文中,我将向你介绍.NET
Framework对多线程应用程序的支持。
首先,为了VB领域里的朋友,我将就线程是什么以及它与一个程序的联系做一个大概而有些简单的介绍。如果你已经学习过C++, Delphi, 或者
Java开发,你可能希望跳过这一部分,因为这些语言有时就是线程自由的。
应用程序,进程和线程
每个运行的Windows的应用程序都有一个进程,它在逻辑上代表了这个应用程序的地址空间,DLL可以加载到这个空间里而变量也可以存储在这里。要完成任何工作,一个进程必须一个执行的路径,或者说线程。多个线程可以在一个单一的进程里运行,而且这些线程都分享其宿主进程的地址空间。(这个概念是重要的,而且我将在后面对它进行更多的讨论。Windows会象在多个进程之间分割时间片一样在多个线程之间进行时间分配。这就给了一个进程在同一时间里完成多个任务的能力。)
Thread 对象
好了,所有的非VB人士都可以回来了。.Net Framework 提供了一个面向对象的API来创建并操作线程,它们在表面上是容易使用的。Thread 对象存在于System.Treading
命名空间里。Thread 的每一个实例都代表了应用程序进程空间里一个不同的线程。图A列出了Thread 对象一些重要的方法和属性。
图A
Thread 类成员 | 解释 |
CurrentThread (static/shared) | 返回对当前正在执行的线程的Thread对象引用 |
IsAlive | 如果当前线程正在运行则返回真值 |
ThreadState | 返回一个枚举类型指出线程的状态 |
Priority | 返回或者设置一个线程时间分片的优先级,或者说一个进程时间片的多大一个部分将分配给这个线程。 |
Abort | 杀死一个线程并抛出一个不可捕获的ThreadAbortException |
Sleep | 使得一个线程挂起一段指定的时间 |
Interrupt | 重新启动或者唤醒一个线程并抛出一个ThreadInterruptedException(如果线程并没有睡眠,那么这个中断被队列缓冲起来直到下一次Sleep 操作。) |
Start | 开始一个线程的操作 |
Suspend | 暂停一个线程的操作 |
Resume | 恢复一个挂起的线程的运行 |
Join | 挂起调用的线程直到引用的线程上的操作已经结束 |
Thread 对象的方法和属性
Thread的构造函数接受一个方法的地址作为参数,当线程运行的时候这个方法就会在这个线程上运行。这个地址在微软的文档中被称作“代理”或者说“代理方法。”要在VB.NET中创建一个代理,你应该在一个方法上使用AddressOf关键字,而你在C#中则应该创建一个新的ThreadStart对象。COM程序员可能认为一个代理应该是一个类方法,但是对于.NET来说却不是这么一回事。被传递给构造函数的方法是类方法还是静态的方法并不重要;任何一种方法都能让我们达到目的。
要在一个新的线程上执行代理,你应该调用Start方法。相信我,这一步是很容易被忘记的,所以在你抓耳挠腮的想你的代理为什么没有被调用的时候,你应该检查一下你是否已经调用了Start方法。Start方法会很快返回,但是在使一个线程工作的时候还有一些额外的工作,所以不要认为你的主程序调用了Start方法你的线程就在运行了。检查一个thread的IsAlive方法来看看它是否真的已经开始运行了。一旦一个线程已经在运行了,它就会继续运行下去,直到它的代理方法完成,或者它的进程结束了,或者它被其它的线程停止了。