概念
一个进程可以划分为若干个独立的执行流,这些独立的执行流称为线程。
任何一个C#程序都有一个默认的线程,该线程称为主线程。主线程执行程序中Main方法中的代码。Main方法中的每一条语句都由主线程执行,当Main返回时,主线程也自动终止。
除了主线程外,还可以创建其他线程,其他的线程可以与主线程一起并行执行。主线程之外
的其他线程称为辅助线程。
Thread
Thread类位于System.Threading命名空间下。
Thread类是用于创建和控制线程的,对线程的常用操作有:启动线程、终止线程、合并线程和让线程休眠等。
Thread类提供的常用属性
1、IsAlive属性:获取一个值,该值指示当前线程的执行状态。如果此线程已启动并且尚未正常终止,则为true;否则为false
2、IsBackground属性:获取或设置一个值,该值指示某个线程是否为后台线程。是后台线程或即将成为后台线程,则为true;否则为false
3、Priority属性:获取或设置一个值,该值指示线程的调度优先级
Thread类提供的常用方法
1、Start方法:启动线程。
2、Join方法:将指定的线程合并到当前线程中,并阻止当前线程执行,直到指定的线程终止或经过了指定的时间为止。
3、Sleep方法:将当前线程阻止指定的毫秒数,零(0)表示应挂起此线程以使其他等待线程能够执行。
4、Abort方法:在调用此方法的线程上引发ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程
前台线程与后台线程
1、一个线程要么是后台线程要么是前台线程。
2、后台线程与前台线程类似,区别是后台线程不会影响进程终止。属于某个进程的所有前台线程都终止后,公共语言运行库就会结束该进程,而且所有属于该进程的后台线程也都会立即停止,而不管后台工作是否完成。
3、利用Thread对象的IsBackground属性,可以设置或判断一个线程是后台线程还是前台线程。
4、通过将某个线程的IsBackground属性设置为true,使其变为后台线程。
5、默认情况下,属于托管线程池的线程(即其IsThreadPoolThread属性为true的线程)都是后台线程,通过创建并启动新的Thread对象而生成的线程都是前台线程。
class1 c1 = new Class1( );
Thread nyThread = new Thread (c1.Method1);
myThread.IsBackground = true;
启动线程
启动线程前,首先要创建一个线程。
创建无参数线程的一般形式为:
Thread t1 = new Thread(线程名);
创建带参数线程的一般形式为(传递一个Object类型的参数):
Thread t2 = new Thread(线程名(Object obj));
对于不止一个参数的情况,可以先将这些参数封装到一个类中,然后传递该类的实例,在线程中,再通过该实例访问相应的数据,从而达到启动线程时传递多个参数的目的。
创建线程实例后,就可以调用Start方法启动线程了。例如:
t1.Start(); //不带参数
t2.Start(“myClass”); //带参数
注意:
调用Start只是告诉系统启动该线程,但是系统并不一定会立即启动它。
终止线程
两种方法:
1、事先设置一个布尔字段,在其他线程中通过修改该布尔量的值作为传递给该线程是否需要终止的判断条件,而在该线程中循环判断该布尔值,以确定是否退出线程,这是结束线程比较好的方法,实际应用中一般使用这种方法。
2、调用Thread类的Abort方法,该方法的最终效果是强行终止线程。
暂停线程
调用Thread类的Sleep方法可以实现这个功能。例如:
Thread.Sleep(1000);
这条语句的功能是让当前线程暂停1000毫秒。
在一个线程中操作另一个线程的控件
默认情况下,在Windows应用程序中,.NET Framework不允许在一个线程中直接操作另一个线程中的控件,这是因为访问Windows窗体控件本质上不是线程安全的。
在应用程序中,如果创建某控件的线程之外的其他线程试图调用该控件,则系统会引发一个InvalidOperationException异常。
有两种办法可以解决这个问题:
(1)使用委托(delegate)操作另一个线程中的控件
(2)用BackgroundWorker组件在后台执行线程
delegate void AppendStringDelegate(string str);
private void AppendString(string str)
{
if(richTextBox1.InvokeRequired)
{
AppendStringDelegate d = AppendString;
richTextBox1.Invoke(d, str); }
else
{ richTextBox1.Text += str; }
}