多线程
进程
进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源
一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。
进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。
一个进程可以创建一个或多个线程以执行与该进程关联的部分程序代码。
线程
线程(Thread)是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。
在.NET应用程序中,都是以Main()方法作为入口的,当调用此方法时系统就会自动创建一个主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。
在C#中,线程是使用Thread类处理的,该类在System.Threading命名空间中。
多线程
多线程的优点:
可以同时完成多个任务;
可以使程序的响应速度更快;
可以让占用大量处理时间的任务或当前没有进行处理的任务定期将处理时间让给别的任务;
可以随时停止任务;
可以设置每个任务的优先级以优化程序性能
多线程的缺点:
(1)线程也是程序,所以线程需要占用内存,线程越多,占用内存也越多。
(2)多线程需要协调和管理,所以需要占用CPU时间以便跟踪线程。
(3)线程之间对共享资源的访问会相互影响,必须解决争用共享资源的问题。
(4)线程太多会导致控制太复杂,最终可能造成很多程序缺陷。
创建多线程的步骤:
1、编写线程所要执行的方法
2、实例化Thread类,并传入一个指向线程所要执行方法的委托。(这时线程已经产生,但还没有运行)
3、调用Thread实例的Start方法,标记该线程可以被CPU执行了,但具体执行时间由CPU决定
System.Threading.Thread类:
名称 |
说明 |
初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托。要执行的方法是有参的。 |
|
初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托,并指定线程的最大堆栈大小 |
|
初始化 Thread 类的新实例。要执行的方法是无参的。 |
|
初始化 Thread 类的新实例,指定线程的最大堆栈大小。 |
线程的常用属性
属性名称 |
说明 |
CurrentContext |
获取线程正在其中执行的当前上下文。 |
CurrentThread |
获取当前正在运行的线程。 |
ExecutionContext |
获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。 |
IsAlive |
获取一个值,该值指示当前线程的执行状态。 |
IsBackground |
获取或设置一个值,该值指示某个线程是否为后台线程。 |
IsThreadPoolThread |
获取一个值,该值指示线程是否属于托管线程池。 |
ManagedThreadId |
获取当前托管线程的唯一标识符。 |
Name |
获取或设置线程的名称。 |
Priority |
获取或设置一个值,该值指示线程的调度优先级。 |
ThreadState |
获取一个值,该值包含当前线程的状态。 |
线程的优先级别
成员名称 |
说明 |
Lowest |
可以将 Thread 安排在具有任何其他优先级的线程之后。 |
BelowNormal |
可以将 Thread 安排在具有 Normal 优先级的线程之后,在具有 Lowest 优先级的线程之前。 |
Normal |
默认选择。可以将 Thread 安排在具有 AboveNormal 优先级的线程之后,在具有BelowNormal 优先级的线程之前。 |
AboveNormal |
可以将 Thread 安排在具有 Highest 优先级的线程之后,在具有 Normal 优先级的线程之前。 |
Highest |
可以将 Thread 安排在具有任何其他优先级的线程之前。 |
System.Threading.Thread的方法
方法名称 |
说明 |
Abort() |
终止本线程。 |
GetDomain() |
返回当前线程正在其中运行的当前域。 |
GetDomainId() |
返回当前线程正在其中运行的当前域Id。 |
Interrupt() |
中断处于 WaitSleepJoin 线程状态的线程。 |
Join() |
已重载。 阻塞调用线程,直到某个线程终止时为止。 |
Resume() |
继续运行已挂起的线程。 |
Start() |
执行本线程。 |
Suspend() |
挂起当前线程,如果当前线程已属于挂起状态则此不起作用 |
Sleep() |
把正在运行的线程挂起一段时间。 |
线程同步:所谓同步:是指在某一时刻只有一个线程可以访问变量。
线程异步:不会等待方法的完成,会直接进入下一行,是非阻塞的。
总结一下同步方法和异步方法的区别:
1、同步方法由于主线程忙于计算,所以会卡住界面。
异步方法由于主线程执行完了,其他计算任务交给子线程去执行,所以不会卡住界面,用户体验性好。
2、同步方法由于只有一个线程在计算,所以执行速度慢。
异步方法由多个线程并发运算,所以执行速度快,但并不是线性增长的(资源可能不够)。多线程也不是越多越好,只有多个独立的任务同时运行,才能加快速度。
3、同步方法是有序的。
异步多线程是无序的:启动无序,执行时间不确定,所以结束也是无序的。一定不要通过等待几毫秒的形式来控制线程启动/执行时间/结束。