实例程序说明
本文的实例程序包括一个列表框、三个按钮。程序使用一个新的线程来运行一个后台处理,结果在列表框中显示。按钮button1启动一个计算平方的线程。按钮button2停止后台处理线程。按钮button3退出程序。程序运行情况如图1所示。

使用线程
首先创建运行在新线程上的后台任务。表1所示的代码执行一个相当长的运行处理----一个无限循环。
表1、后台处理程序
private void BackgroundProcess()
{
int i= 1;
while(true)
{
// 向列表框增加一个项目
listBox1.Items.Add("Iterations: " + i.ToString ());
i ++;
Thread.Sleep(2000); // 指定线程休眠的时间
}
}
这段代码无限循环,每次执行时在列表框中加入一个项目。
在规定好一个工作的处理代码以后,就需要将这段代码分配给一个线程,并且启动它。为此需要使用线程对象(Thread object),它是.NET架构类中System.Threading命名空间的一部分。在实例化一个新的线程类时,需要把在线程类构造器中执行的代码块的一个引用传送给该实例。表2所示的代码创建一个新的线程对象,并且将BackgroundProcess的一个引用传送给该对象。
表2、线程的使用
Thread t1,t2; // 说明为窗体类成员
t1 = new Thread(new ThreadStart(BackgroundProcess));
t1.Start(); // 以上2行放置在窗体的load事件中
ThreadStart表示在线程上执行的方法,这里是一个到BackgroundProcess方法的委派对象。在C#中,一个委派是一个类型安全、面向对象的函数指针。在实例化该线程后,可以通过调用线程的Start()方法来开始执行代码。
控制线程
在线程启动以后,可以通过调用线程对象的方法来控制线程的状态。可以通过调用Thread.Sleep方法来暂停一个线程的执行,这个方法可以接收一个整型值,用来决定线程休眠的时间。对于本文的实例程序,为了让列表项目增加的速度变慢,在其中放入了一个Sleep方法的调用。
可以通过调用Thread.Sleep(System.Threading.Timeout.Infinite)来让线程进入休眠状态,但是,这个调用的休眠时间是不确定的。要中断这个休眠,可以调用Thread.Interrupt方法。
通过调用Thread.Suspend方法可以挂起线程。挂起可以暂停一个线程,直到另一个线程调用Thread.Resume为止。休眠和挂起的区别是,挂起并不立刻让线程进入一个等待的状态,线程并不会挂起,直到.NET runtime认为现在已经是一个安全的地方来挂起它了,而休眠则会立刻让线程进入一个等待的状态。
表3、停止线程的执行
private void button2_Click
(object sender, System.EventArgs e)
{ t1.Abort(); }
Thread.Abort方法可以停止一个线程的执行。本文的实例程序通过加入一个按钮button2来停止后台处理,在事件处理程序中调用了Thread.Abort方法,如表3所示。
这就是多线程的强大之处。用户界面的响应很快,因为用户界面运行在一个单独的线程中,而后台的处理运行在另外一个线程中。在用户按下按钮button2时,就会马上得到响应,并且停止后台处理。
通过多线程程序传送数据
在实际工作中,还需要使用到多线程的许多复杂特性。其中一个问题就是如何将程序的数据由线程类的构造器传入或者传出。对于放到另外一个线程中的过程,既不能传参数给它,也不能由它返回值,因为传入到线程构造器的过程是不能拥有任何参数或者返回值的。为了解决这个问题,可以将过程封装到一个类中,这样,方法的参数就可使用类中的字段。
本文给出了一个简单的例子,计算一个数的平方。为了在一个新的线程中使用这个过程,将它封装到一个类中,如表4所示。
上一页 下一页






