.net是通过Thread类来描述线程的,线程的创建即构造Thread类即可。
Thread常用的构造函数有两个,分别是:
Thread(ThreadStart) 与 Thread(ParameterizedThreadStart) 。
其中:ThreadStart是一个委托,定义如下:public delegate void ThreadStart()
ParameterizedThreadStart也是一个委托,定义如下:public delegate void ParameterizedThreadStart(Object obj)
二者的区别是ParameterizedThreadStart是一个能够使用一个object对象作为参数的委托。其中参数通过 Thread.Start(Object para)
方式进行参数的确定。
1.1使用ThreadStart创建线程举例:
- using System;
- using System.Threading;
- class Test
- {
- static void Main()
- {
- Thread newThread =
- new Thread(new ThreadStart(Work.DoWork));
- newThread.Start();
- }
- }
- class Work
- {
- Work() {}
- public static void DoWork() {}
- }
当然在使用委托时可以简化使用方式,如:
Thread newThread=new Thread(Work.DoWork);
1.2使用ParameterizedThreadStart创建线程举例:
- using System;
- using System.Threading;
- public class Work
- {
- public static void Main()
- {
- // To start a thread using a shared thread procedure, use
- // the class name and method name when you create the
- // ParameterizedThreadStart delegate. C# infers the
- // appropriate delegate creation syntax:
- // new ParameterizedThreadStart(Work.DoWork)
- //
- Thread newThread = new Thread(Work.DoWork);
- // Use the overload of the Start method that has a
- // parameter of type Object. You can create an object that
- // contains several pieces of data, or you can pass any
- // reference type or value type. The following code passes
- // the integer value 42.
- //
- newThread.Start(42);
- // To start a thread using an instance method for the thread
- // procedure, use the instance variable and method name when
- // you create the ParameterizedThreadStart delegate. C# infers
- // the appropriate delegate creation syntax:
- // new ParameterizedThreadStart(w.DoMoreWork)
- //
- Work w = new Work();
- newThread = new Thread(w.DoMoreWork);
- // Pass an object containing data for the thread.
- //
- newThread.Start("The answer.");
- }
- public static void DoWork(object data)
- {
- Console.WriteLine("Static thread procedure. Data='{0}'",
- data);
- }
- public void DoMoreWork(object data)
- {
- Console.WriteLine("Instance thread procedure. Data='{0}'",
- data);
- }
- }
1.2线程的终止
可以调用Abort方法终止线程。线程是如何终止自己的呢?线程终止的过程是在线程外(比如主线程)调用该线程对象的Abort方法,该方法会使该线程在运行过程中出现一个异常 ThreadAbortException ,该异常可以在线程内被捕捉到。被终止的线程在被Abort以后,不再去执行正常的代码,而是捕获到异常转而执行 catch{}finally{}的代码。这说明,线程并不是立即退出的,而是继续执行一段善后的代码。所以在调用Abort时,最好继续调用Join()函数,让线程执行完善后代码再退出。
如果被终止的线程正在运行中,调用Abort则会中止后续代码的运行;如果被终止的线程处于 WaitSleepJoin状态,那么该线程会被中断然后中止(即线程被唤醒然后中止)。
- using System;
- using System.Threading;
- class Test
- {
- public static void Main()
- {
- Thread newThread = new Thread(new ThreadStart(TestMethod));
- newThread.Start();
- Thread.Sleep(1000);
- // Abort newThread.
- Console.WriteLine("Main aborting new thread.");
- try
- {
- newThread.Abort("Information from Main.");
- }
- catch(ThreadAbortException)
- {
- Console.WriteLine("main catch the ThreadAbortException");
- }
- // Wait for the thread to terminate.
- newThread.Join();
- Console.WriteLine("New thread terminated - Main exiting.");
- }
- static void TestMethod()
- {
- try
- {
- while(true)
- {
- Console.WriteLine("New thread running.");
- Thread.Sleep(1000);
- }
- }
- catch(ThreadAbortException abortException)
- {
- Console.WriteLine((string)abortException.ExceptionState);
- }
- }
- }
- 注:在上述代码中,main函数是无法捕获ThreadAbortException异常的。
1.3线程的阻塞
引起线程阻塞的方法有静态方法Sleep(),因为是静态方法所以只能由线程自身完成阻塞过程,并且线程立即进入阻塞状态。是一种主动的阻塞。
Join()则是阻塞调用线程而等待使工作线程运行完毕。
注意:Thread.CurrentThread.Join()与Sleep()容易产生混淆,二者都是使当前线程阻塞。区别好像是在处理一些非托管的资源时使用 Thread.CurrentThread.Join()而不是Sleep(),MSDN如此解释:“在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。”
1.4线程的唤醒
使用Abort以及Interrupt都能使处于WaitSleepJoin中的线程产生中断唤醒,区别在于Abort是使线程终止,而Interrupt是使中断一个线程仅仅释放它的当前的(或下一个)等待状态,它并不结束这个线程。
ThreadInterruptedException 在中断的线程中引发,但要在该线程阻塞之后才引发。如果该线程一直未阻塞,则一直都不会引发该异常,因而该线程可能无需中断就能完成。下面的例子(稍不同于MSDN上写得),可以看出Interrupt的确没有终止线程。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- namespace InterruptTest
- {
- class Program
- {
- static void Main(string[] args)
- {
- StayAwake stayAwake = new StayAwake();
- Thread newThread =
- new Thread(new ThreadStart(stayAwake.ThreadMethod));
- newThread.IsBackground = true;
- newThread.Start();
- // The following line causes an exception to be thrown
- // in ThreadMethod if newThread is currently blocked
- // or becomes blocked in the future.
- Thread.CurrentThread.Join(100);
- newThread.Interrupt();
- Console.WriteLine("Main thread calls Interrupt on newThread.");
- // Tell newThread to go to sleep.
- //stayAwake.SleepSwitch = true;
- // Wait for newThread to end.
- newThread.Join();
- Console.ReadLine();
- }
- }
- class StayAwake
- {
- bool sleepSwitch = false;
- public bool SleepSwitch
- {
- set { sleepSwitch = value; }
- }
- public StayAwake() { }
- public void ThreadMethod()
- {
- Console.WriteLine("newThread is executing ThreadMethod.");
- while (!sleepSwitch)
- {
- try
- {
- Thread.Sleep(1000);
- Console.WriteLine("sleep again");
- }
- catch (ThreadInterruptedException)
- {
- Console.WriteLine("newThread cannot go to sleep - " + "interrupted by main thread.");
- }
- }
- }
- }
- }