线程解析和认识--------(一)线程初识
在开始讲线程之前,先应该讲一下进程。什么进程?简单点说一个应用程序就是一个进程(当然还有有些程序不止一个进程),Windows操作系统下,为了将应用程序之间隔离,以防止各个应用程序之间的互操作产生各种意外的情况,故引入的进程机制。进程是操作系统中获取CPU分配资源的最小单位,仅仅占有资源。在.NET平台下的应用程序,又在进程中引入了应用程序域,应用程序在运行的时候并不是直接加载运行的,而是先将程序集、.exe程序加载到应用程序域中,然后在启动运行,应用程序域相当于一个轻量级的进程,主要是将各个程序集隔离开来单独运行,这样即使其中一个程序集运行异常也不会影响其他的程序集的运行。线程是进程中最小执行任务的单位,一个进程中可以有多个线程,线程都不占有资源,所有的线程都共享进程所占有的资源。
接下来讨论第二个问题,为什么要使用线程?简单的说,就是为了在程序运行的过程中,还可以进行其他的操作。比如:你在听音乐的时候,播放器一边放音乐、一边可以显示歌词,同时你还可以搜索一些想听的歌,这里就用到了多线程。
第三个问题,如何使用线程?在.NET 线程主要在System.Threading 命名空间下通过Thread类实例来实现。首先来介绍下System.Threading命名空间下的的一些常用的内容,对于一些不常用的内容就不做过多的介绍,如果有兴趣的朋友可以自己去网上查阅。这里只是做一个大概的描述,有关具体的内容在以后的章节中会逐渐讲解。
类 |
描述 |
AutoResetEvent |
该事件通知一个或者多个正在等待的线程事件已经发生。 |
ManualResetEvent |
当通知一个或者多个等待的线程已经发生一个事件时发生 |
Monitor |
这个类提供一个同步访问对象的架构。 |
Mutex |
为一个线程提供共享资源独占访问的一个同步原型。也可用于内部进程同步。 |
ReaderWriterLock |
定义一个允许单写-多读语法。 |
RegisteredWaitHandle |
这个类表示一个当调用RegisterWaitForSingleObject()方法注册的句柄。 |
Thread |
该类创建并控制一个线程,设置线程优先级并获取其状态。 |
ThreadPool |
这个类提供一个可以用来执行工作,处理异步I/O,等待其他线程以及处理定时器的线程池。 |
Timeout |
这个类简单地包含了一个我们想要确定特定时间的常量。 |
Timer |
这个类提供在特定间隔中执行方法的结构。 |
WaitHandle |
该类将等待对一个共享资源独享访问的操作系统对象封装起来 |
下边就先介绍一下我们这个系列主要讲的Thread类。先看一下Thread类下的主要常用的方法和常用属性的简单介绍
常用公共方法名 |
简单的表示描述 |
Abort() |
调用这个方法通常会终止线程。 |
GetData() |
静态方法从当前线程的当前应用程序域特定位置收集数据。 |
GetDomain() |
静态方法返回当前线程所属的当前应用程序域。 |
GetDomainID() |
静态方法返回一个唯一的应用程序域标志。 |
Interrupt() |
这个方法中断状态为WaitSleepJoin的线程。 |
Join() |
重载方法阻塞调用线程直到一个线程终止。 |
ResetAbort() |
静态方法为当前线程取消Abort()请求。 |
Resume() |
这个方法恢复阻塞的线程。 |
SetData() |
静态方法为线程的当前程序域设定数据。 |
Sleep() |
静态重载方法按照特定毫秒阻塞当前线程。 |
SpinWait() |
静态方法导致一个线程等待由迭代参数定义的时间。 |
Start() |
启动线程,并将状态置成ThreadState.Running. |
Suspend() |
阻塞线程,如果当前线程已经阻塞,会不起作用。 |
现在让我们看看另外一张表,这次包含了线程的公共属性。
常用公共属性名 |
简单的描述 |
CurrentContext |
这个静态属性获取正在执行的线程的上下文。 |
CurrentThread |
这个静态属性获取当前正在运行的线程。 |
IsAlive |
获取当前线程执行状态值。 |
IsBackground |
获取或设置当前线程是不是后台线程。 |
IsThreadPoolThread |
获取当前线程是不是一个线程池的一部分。 |
Name |
获取或者设置当前线程名。 |
Priority |
获取或者设置一个线程的执行优先级。 |
ThreadState |
获取当前线程的状态。 |
通过以上的这些介绍相信你对线程已经有一个基本的认识了,下面我带领大家一步一步的做一些实例,来巩固对以上内容的认识。
我们知道每一个应用程序都有一个主线程,我们称之为(Main Thread),这个线程是操作系统为自动应用程序创建的,在WinForm应用程序中,如果想要在一个线程中改变控件的属性、状态,必须是得在创建这个控件的线程中进行控制,也就是我们通常说的UI线程,也就是主线程,如果在其他的线程中修改控件的属性、状态,一定会引发异常的,那么如何实现呢?我会在以后跟大家慢慢讲解。
下面是一个创建线程的小例子(一般的线程多用于比较耗时的操作,比如网络连接、计算、从数据库读写大量的数据等)
static void Main(string[] args)
{
//标记显示主线程ID
Console.WriteLine("主线程的ID:" + Thread.CurrentThread.ManagedThreadId); Thread thread = new Thread(new ThreadStart(Count));//线程的构造函数有四个,这次先讲的是线程调用无参的函数,需要经过ThreadStart类进行封装一下,下一节会将线程调用有参的函数)
thread.Start();
Console.ReadKey();
}
private static void Count()
{
int sum = 0;
for (int i = 1; i < 1000000000; i++)
{
sum =sum+i;
}
Console.WriteLine("当前的线程ID:" + Thread.CurrentThread.ManagedThreadId);//标记显示当前线程ID
Console.WriteLine("计算结果为:"+(sum));
}
运算结果如下:
该程序显示了用一个新建的线程来计算1-10000000000累加的结果,实验结果表明,通过Thread新建的线程实例对象跟主线程不是同一个线程,这个我们会在后边陆续介绍。好了,今天就到这了。希望可以对大家有所帮助。