聚拓互联

http://www.ejutuo.com
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

第三章:多线程技术——操作线程

Posted on 2011-06-04 22:23  聚拓互联  阅读(653)  评论(0编辑  收藏  举报

<二> 操作线程

1、创建线程

   创建线程是Thread类的实例。Thread类是.NET Framework类库中的类,而且位于System.Threading名称空间中。因此,为创建Thread类的实例,首先要导入System.Threading名称空间。然后可以创建代表线程的Thread类对象。通过创建Thread类对象的多个实例,就可以在应用程序继承添加线程。

   创建线程需要声明Thread类的对象,并提供线程开始执行的方法细节。为了达到这个目的,需要使用System.Threading名称空间中的public void委托ThreadStart()。

例:创建一个线程并启动

using System;

using System.Collections;

using System.Threading;

namespace 笔记

{

    class MyThread

    {

        public void Method()

        {

            Console.WriteLine("创建一个新的线程并启动");

        }

        public static void MMain()

        {

            MyThread NewMyThread = new MyThread();

            Thread NewThread = new Thread(new ThreadStart(NewMyThread.Method)); //创建新的线程

            NewThread.Start();   //启动线程

          注意:new ThreadStart()实际上是委托实例。

        }

    }

}

程序运行结果:

创建一个新的线程并启动

  在这里,创建了Thread(线程)类的实例NewThread。ThreadStart()委托指定了NewThread开始执行的方法是Method,Method是MyThread类中定义的public void函数(方法)。创建线程后,调用Start()启动线程。

   提示:因为可以在多个应用程序中使用定义的线程,因此建议用相关的名称为线程命名,这使得其他程序员可以重用您的线程所提供的功能。要用相关名称为线程命名,需要修改线程的Name特性值。

   下面的代码定义了工作线程,它可以更新主控数据库中的记录,这段代码为线程起了一个有意义的名称,例如Update Records Thread。

   Thread MyThread=new Thread(new ThreadStart(newClass.Method));

   Thread.Name=“Update Records Thread”;

   第一行代码创建了Thread类的实例,其名称是MyThread,然后将名称Update Records Thread赋予线程。

   除了可以为线程起有意义的Name属性之外,可以使用特性了解正在执行的线程的状态。System.Threading名称空间中的Thread类定义了这些属性。

◆ IsAlive属性:IsAlive属性用于确定线程的执行过程是否已经结束或者线程仍然处于执行状态。对于处于执行状态的线程,IsAlive特性返回布尔值true,对于没有执行的线程,返回false。

◆ ThreadState属性:ThreadStatic属性指出了线程的执行状态。换句话说,它返回的值说明是否已经开始执行线程。

 

2、终止线程 *

   前面已经介绍了创建和执行线程。然而,有时可能需要终止正在运行的线程。仍然考虑前面已经使用过的例子,用打印100页。在这种情况下,执行线程打印所需要的页面内容。如果需要打印其他一些急需的页面,则需要停止当前打印命令,或者,换句话说,终止正在打印100页的线程。

   C#提供了一个基类Thread,它可以对线程执行几种操作。Thread包含几个预定义的方法,它们可以处理线程。为终止线程,要使用Thread类的Abort()方法。语法如下:

   MyThread.Abort()

   在这里,MyThread是Thread类的实例。Abort()方法没有任何参数。当调用Abort()方法时,C#编译器可能并不会立即终止线程。要理解为什么C#编译器需要一定的时间来终止线程,首先要理解如何执行Abort()方法。

   当调用Thread类的Abort()方法时,线程引发TreadAbortException异常。除了用于处理线程的基类之外,C#提供了产生异常基类。ThreadAbortException是ThreadAbortException类的异常。C#并没有提供任何机制来处理这种异常。换句话说,如果尝试在try块内终止正在执行的线程,则C#编译器在终止线程之前首先执行相关的finally块。

   可以看到,与立即杀死目标线程的日期环境相比,.NET提供了一种机制,可以更加安全地终止线程。

 

3、阻塞线程 *

   C#允许在C#编译器继续执行另一个线程之前,等待某个线程结束执行。为了达到这个目的,Thread类包含了Join方法来实现。语法如下:

  MyThread.Join();

   前面的语句调用Thread类的Join方法,以等待MyThread结束执行。如果并不知道需要多长时间线程才能结束执行,则可以规定C#编译器在开始执行下一个线程之前等待的最长时间。如果没有指定最长时间限制,则编译器等待线程自己终止。

   Join()方法通常和Abort()方法一起使用。前面解释过,当调用Abort()方法时,如果线程处于try块中,则不会立即终止线程。这暗示着,在终止线程之前,需要执行finally语句。然而,程序员可能并不知道C#编译器执行finally所需要的时候,而且并不准备等待很长的时间。因此可以调用Abort()方法,然后调用Join()方法,以终止线程。

 

4、挂起线程

   前面已经介绍了如何终止线程。在终止线程之后,就不能继续执行线程。然而,当挂起线程时,可以在需要的时候继承执行线程。暂停执行线程需要使用Suspend()方法。Suspend()方法是Thread类的另一个方法,而且没有任何参数。语法如下:

   MyThread.Suspend();

   Suspend()方法并不会永久杀死线程。它仅仅在一段时间内停止执行线程,然后可以继续执行。因此,当需要重新开始执行线程时,要调用Thread类的另一个方法:Resume()方法。Resume()方法从线程挂起的点开始执行线程。语法如下:

   MyThread.Resume();

   与Abort()方法类似,Suspend()方法并不会立即停止执行目标线程。在挂起线程之前,它等待线程达到安全点。因此,线程可以调用Suspend()方法挂起本身或者另一个线程。

   例如,如果MyThread挂起了本身,则另一个线程需要调用Resume()方法来重新开始执行这个线程。然而,如果MyThread挂起了另一个线程,如YourThread,则在MyThread在YourThread上调用Resume()方法之前,不会继续执行YourThread。

除了Suspend()方法之外,可以调用Thread类的Sleep()方法阻塞线程的执行。

 

5、线程休眠

   Thread类包含另一个方法Sleep(),将当前线程阻塞指定的毫秒数。通过作为参数向Sleep()方法传递时间,就可以指定停止线程的时间。规定时间的单位是毫秒。下面的这个例子使得线程休眠两秒。

   Thread.Sleep(2000);

   正如上面的代码所说明的那样,由类本身调用Sleep()方法,而不是类的实例。

那么,Sleep()方法和Suspend()有什么不同呢?如下表:

Suspend()方法

Sleep()方法

Suspend()方法用于阻塞线程的执行,直到调用Resume()方法

Sleep()方法用于在指定时间内阻塞线程的执行过程

Suspend()方法并不会立即挂起所请求的线程

Sleep()方法立即阻塞所请求的执行过程

可以调用Suspend()方法阻塞另一个线程的执行过程

不能调用Sleep()方法阻塞另一个线程的执行过程

为调用Suspend()方法,要使用实例名称

为调用Sleep()方法,要使用类型名称