线程实用解析--------(一)线程初识
在开始讲线程之前,先应该讲一下进程。什么进程?简单点说一个应用程序就是一个进程(当然还有有些程序不止一个进程),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新建的线程实例对象跟主线程不是同一个线程,这个我们会在后边陆续介绍。好了,今天就到这了。希望可以对大家有所帮助。