C# 进程、线程和多线程
1.进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。
2.线程:在任务管理器里面查询当前总共运行的线程数,线程(Thread)是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。在.NET应用程序中,都是以Main()方法作为入口的,当调用此方法时系统就会自动创建一个主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。
3.多线程的优点:可以同时完成多个任务;可以使程序的响应速度更快;可以让占用大量处理时间的任务或当前没有进行处理的任务定期将处理时间让给别的任务;可以随时停止任务;可以设置每个任务的优先级以优化程序性能。
4.多线程的不利:
(1)线程也是程序,所以线程需要占用内存,线程越多,占用内存也越多。
(2)多线程需要协调和管理,所以需要占用CPU时间以便跟踪线程。
(3)线程之间对共享资源的访问会相互影响,必须解决争用共享资源的问题。
(4)线程太多会导致控制太复杂,最终可能造成很多程序缺陷。
5.一个进程可以创建一个或多个线程以执行与该进程关联的部分程序代码。
6.在C#中,线程是使用Thread类处理的,该类在System.Threading命名空间中。
7.创建多线程的步骤:
(1)编写线程所要执行的方法
(2)实例化Thread类,并传入一个指向线程所要执行方法的委托。(这时线程已经产生,但还没有运行)
(3)调用Thread实例的Start方法,标记该线程可以被CPU执行了,但具体执行时间由CPU决定
8.线程的标识符:ManagedThreadId是确认线程的唯一标识符,程序在大部分情况下都是通过Thread.ManagedThreadId来辨别线程的。而Name是一个可变值,在默认时候,Name为一个空值 Null,开发人员可以通过程序设置线程的名称,但这只是一个辅助功能。
9.线程的优先级别:当线程之间争夺CPU时间时,CPU按照线程的优先级给予服务。高优先级的线程可以完全阻止低优先级的线程执行。.NET为线程设置了Priority属性来定义线程执行的优先级别,里面包含5个选项,其中Normal是默认值。除非系统有特殊要求,否则不应该随便设置线程的优先级别。
10.线程的状态:通过ThreadState可以检测线程是处于Unstarted、Sleeping、Running 等等状态,它比 IsAlive 属性能提供更多的特定信息。前面说过,一个应用程序域中可能包括多个上下文,而通过CurrentContext可以获取线程当前的上下文。CurrentThread是最常用的一个属性,它是用于获取当前运行的线程。
11.Thread 中包括了多个方法来控制线程的创建、挂起、停止、销毁,以后来的例子中会经常使用。
12.前台线程:只有所有的前台线程都结束,应用程序才能结束。默认情况下创建的线程都是前台线程
后台线程:只要所有的前台线程结束,后台线程自动结束。通过Thread.IsBackground设置后台线程。必须在调用Start方法之前设置线程的类型,否则一旦线程运行,将无法改变其类型。
13.线程同步:所谓同步:是指在某一时刻只有一个线程可以访问变量。
如果不能确保对变量的访问是同步的,就会产生错误。
14.
同步和异步是对方法执行顺序的描述。
同步:等待上一行完成计算之后,才会进入下一行。
例如:请同事吃饭,同事说很忙,然后就等着同事忙完,然后一起去吃饭。
异步:不会等待方法的完成,会直接进入下一行,是非阻塞的。
15.线程的常用属性
CurrentContext |
获取线程正在其中执行的当前上下文。 |
CurrentThread |
获取当前正在运行的线程。 |
ExecutionContext |
获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。 |
IsAlive |
获取一个值,该值指示当前线程的执行状态。 |
IsBackground |
获取或设置一个值,该值指示某个线程是否为后台线程。 |
IsThreadPoolThread |
获取一个值,该值指示线程是否属于托管线程池。 |
ManagedThreadId |
获取当前托管线程的唯一标识符。 |
Name |
获取或设置线程的名称。 |
Priority |
获取或设置一个值,该值指示线程的调度优先级。 |
ThreadState |
获取一个值,该值包含当前线程的状态。 |
16.线程的方法:
Abort() |
终止本线程。 |
GetDomain() |
返回当前线程正在其中运行的当前域。 |
GetDomainId() |
返回当前线程正在其中运行的当前域Id。 |
Interrupt() |
中断处于 WaitSleepJoin 线程状态的线程。 |
Join() |
已重载。 阻塞调用线程,直到某个线程终止时为止。 |
Resume() |
继续运行已挂起的线程。 |
Start() |
执行本线程。 |
Suspend() |
挂起当前线程,如果当前线程已属于挂起状态则此不起作用 |
Sleep() |
把正在运行的线程挂起一段时间。 |