【C#】线程与进程

C#多线程

一.进程和线程基本概念
进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。
一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或多个线程。
线程是操作系统分配处理器时间的基本单元,在进程中可以有多个线程同时执行代码。
进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),
一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。
进程可以理解为一个程序的基本边界。是应用程序的一个运行例程,是应用程序的一次动态执行过程。

线程(Thread)是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,
在进程入口执行的第一个线程被视为这个进程的主线程。在.NET应用程序中,都是以Main()方法作为入口的,
当调用此方法时系统就会自动创建一个主线程。线程主要是由CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。
CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,
TLS主要用于存放线程的状态信息。

二.多线程
多线程的优点:
(1)可以同时完成多个任务;
(2)可以使程序的响应速度更快;
(3)可以让占用大量处理时间的任务或当前没有进行处理的任务定期将处理时间让给别的任务;
(4)可以随时停止任务;
(5)可以设置每个任务的优先级以优化程序性能。

多线程的缺点:
(1)线程也是程序,所以线程需要占用内存,线程越多,占用内存也越多。
(2)多线程需要协调和管理,所以需要占用CPU时间以便跟踪线程。
(3)线程之间对共享资源的访问会相互影响,必须解决争用共享资源的问题。
(4)线程太多会导致控制太复杂,最终可能造成很多程序缺陷。

当启动一个可执行程序时,将创建一个主线程。在默认的情况下,C#程序具有一个线程,
此线程执行程序中以Main方法开始和结束的代码,Main()方法直接或间接执行的每一个命令都有默认线程
(主线程)执行,当Main()方法返回时此线程也将终止。

一个进程可以创建一个或多个线程以执行与该进程关联的部分程序代码。在C#中,线程是使用Thread类处理的,
该类在System.Threading命名空间中。使用Thread类创建线程时,只需要提供线程入口,
线程入口告诉程序让这个线程做什么。通过实例化一个Thread类的对象就可以创建一个线程。
创建新的Thread对象时,将创建新的托管线程。Thread类接收一个ThreadStart委托或
ParameterizedThreadStart委托的构造函数,该委托包装了调用Start方法时由新线程调用的方法。 //启动线程

创建多线程的步骤:
1、编写线程所要执行的方法
2、实例化Thread类,并传入一个指向线程所要执行方法的委托。(这时线程已经产生,但还没有运行)
3、调用Thread实例的Start方法,标记该线程可以被CPU执行了,但具体执行时间由CPU决定

三.System.Threading.Thread类
Thread类是是控制线程的基础类,位于System.Threading命名空间下,具有4个重载的构造函数:

名称/说明
Thread(ParameterizedThreadStart)
初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托。要执行的方法是有参的。

Thread(ParameterizedThreadStart, Int32) 初始化 Thread 类的新实例,指定允许对象在线程启动时传递给线程的委托,并指定线程的最大堆栈大小

Thread(ThreadStart)
初始化 Thread 类的新实例。要执行的方法是无参的。

Thread(ThreadStart, Int32)
初始化 Thread 类的新实例,指定线程的最大堆栈大小。

ThreadStart是一个无参的、返回值为void的委托。委托定义如下:
public delegate void ThreadStart()
另外也可以通过匿名委托或Lambda表达式来为Thread的构造方法赋值

ParameterizedThreadStart是一个有参的、返回值为void的委托,定义如下:
public delegate void ParameterizedThreadStart(Object obj)
注意:ParameterizedThreadStart委托的参数类型必须是Object的。如果使用的是不带参数的委托,
不能使用带参数的Start方法运行线程,否则系统会抛出异常。但使用带参数的委托,
可以使用thread.Start()来运行线程,这时所传递的参数值为null。

四.线程的常用属性

属性名称/说明
CurrentContext 获取线程正在其中执行的当前上下文。
CurrentThread 获取当前正在运行的线程。
ExecutionContext 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
IsAlive 获取一个值,该值指示当前线程的执行状态。
IsBackground 获取或设置一个值,该值指示某个线程是否为后台线程。
IsThreadPoolThread 获取一个值,该值指示线程是否属于托管线程池。
ManagedThreadId 获取当前托管线程的唯一标识符。
Name 获取或设置线程的名称。
Priority 获取或设置一个值,该值指示线程的调度优先级。
ThreadState 获取一个值,该值包含当前线程的状态。

1.线程的标识符
ManagedThreadId是确认线程的唯一标识符,程序在大部分情况下都是通过Thread.ManagedThreadId来辨别线程的。
而Name是一个可变值,在默认时候,Name为一个空值 Null,开发人员可以通过程序设置线程的名称,
但这只是一个辅助功能。

2.线程的优先级别
当线程之间争夺CPU时间时,CPU按照线程的优先级给予服务。高优先级的线程可以完全阻止低优先级的线程执行。
.NET为线程设置了Priority属性来定义线程执行的优先级别,里面包含5个选项,其中Normal是默认值。
除非系统有特殊要求,否则不应该随便设置线程的优先级别。

成员名称 说明
Lowest 可以将 Thread 安排在具有任何其他优先级的线程之后。
BelowNormal 可以将 Thread 安排在具有 Normal 优先级的线程之后,在具有 Lowest 优先级的线程之前。
Normal 默认选择。可以将 Thread 安排在具有 AboveNormal 优先级的线程之后,在具有 BelowNormal 优先级的线程之前。
AboveNormal 可以将 Thread 安排在具有 Highest 优先级的线程之后,在具有 Normal 优先级的线程之前。
Highest 可以将 Thread 安排在具有任何其他优先级的线程之前。

3.线程的状态
通过ThreadState可以检测线程是处于Unstarted、Sleeping、Running 等等状态,它比 IsAlive 属性能提供更多的特定信息。
而通过CurrentContext可以获取线程当前的上下文。
CurrentThread是最常用的一个属性,它是用于获取当前运行的线程。

4.System.Threading.Thread的方法
Thread 中包括了多个方法来控制线程的创建、挂起、停止、销毁,以后来的例子中会经常使用。

方法名称 说明
Abort()     终止本线程。
GetDomain() 返回当前线程正在其中运行的当前域。
GetDomainId() 返回当前线程正在其中运行的当前域Id。
Interrupt() 中断处于 WaitSleepJoin 线程状态的线程。
Join() 已重载。 阻塞调用线程,直到某个线程终止时为止。
Resume() 继续运行已挂起的线程。
Start()   执行本线程。
Suspend() 挂起当前线程,如果当前线程已属于挂起状态则此不起作用
Sleep()   把正在运行的线程挂起一段时间。

五.前台线程和后台线程
前台线程:只有所有的前台线程都结束,应用程序才能结束。默认情况下创建的线程
都是前台线程
后台线程:只要所有的前台线程结束,后台线程自动结束。通过Thread.IsBackground设置后台线程。
必须在调用Start方法之前设置线程的类型,否则一旦线程运行,将无法改变其类型。

PS:通过BeginXXX方法运行的线程都是后台线程。

PS:后台线程一般用于处理不重要的事情,应用程序结束时,后台线程是否执行完成对整个应用程序没有影响。
如果要执行的事情很重要,需要将线程设置为前台线程。

六.线程间资源的共享
1.如果多个线程对同一个对象实例有相同的引用,这些线程就共享这个对象实例的数据。
2.静态字段提供另外一种共享数据的方法,静态字段被所有线程所共享。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值