- 线程(Thread)与进程(Process)
线程是一个可执行路径,它可以独立于其他线程执行
每个线程都在操作系统的进程(Process)内执行,而操作系统进程提供了程序远行的独立环境
根据线程可分为:
单线程应用,在进程的独立环境里只跑一个线程,所以该线程拥有独占权;
多线程应用,当单个线程中共会跑多个线程,它们会共享当前执行环境(尤其是内存);
2在C#中提供的一个Thread类创建和控制线程,设置其优先级并获取其状态;
命名空间:System.Threading
程序集:System.Threading.Thread.dll
.NET6中为Thread提供的属性
| 属性名称 | 作用 |
| ApartmentState | 获取或设置此线程的单元状态 |
| CurrentCulture | 获取或设置当前线程的区域性 |
| CurrentPrinicipal | 获取或设置线程的当前负责人 |
| CurrentThread | 获取当前正在运行的线程 |
| CurrentUICulture | 获取或设置资源管理器使用当前区域性以便在运行时查找区域性特定的资源 |
| ExecutionContext | 获取ExecutionContext对象,该对象包含有关当前线程的各种上下文的信息 |
| IsAlive | 获取指示当前线程的执行状态的值 |
| IsBackground | 获取或设置一个值,该值指示某个线程是否为后台线程 |
| IsThreadPoolThread | 获取指示线程是否属于托管线程池的值 |
| ManagedThreadld | 获取当前托管线程的唯一标识符 |
| Name | 获取或设置线程的名称 |
| Priority | 获取或设置指示线程的调度优先级的值 |
| ThreadState | 获取一个值,该值包含当前线程的状态 |
.NET 6为Thread提供的方法
| 方法名称 | 作用 |
| AllocateDataSlot() | 在所有线程上分配未命名的数据槽.为了获得更好的性能,请改用以ThreadStaicAttribute特性标记的字段 |
| AllocateNameDataSlot(String) | 在所有线程上分配未命名的数据槽.为了获得更好的性能,请改用以ThreadStaicAttribute特性标记的字段 |
| BeginCriticalRegin() | 通知宿主执行将要进入一个代码区域,在该代码区域内线程中止或未经处理异常的影响可能会危害有应用程序域中的其他任务 |
| BeginThreadAffinity() | 通知主机托管代码将要执行依赖于当前物理操作系统线程的标识的指令 |
| DisableComObjectEagerCleanup() | 对于当前线程关闭远行时可调用包装(RCW)的自动清理 |
| EndCriticalRegion() | 通知主机执行将要进入一个代码区域,在该代码区域内线程中止或未经处理异常的影响限于当前任务 |
| EndThreadAffinity() | 通知主机托管代码已执行完依赖于当前物理操作系统线程的标识的指令 |
| Finalize() | 确保垃圾回收Thread对象时释放资源并执行其他清理操作 |
| FreeNamedDataSlot(String) | 为进程中所有线程消除名称与槽之间的关联.为了获得更好的性能,请改用以ThreadStaticAttribute特性标记的字段 |
| GetApartmentState() | 返回表示单元状态的ApartmentState值 |
| GetCompressedStack() | 返回CompressedStack对象,此对象可用于获取当前线程的堆栈. |
| GetCurrentProcessorld() | 获取用于指示当前线程正在哪个处理器上执行的ID |
| GetData(LocalDataStoreSlot) | 在当前线程的当前域中从当前线程上指定的槽中检索值.为了获取更好的性能,请改用以ThreadStaticAttribute特性标记的字段 |
| GetDomain() | 返回当前线程正在其中运行的当前域 |
| GetDomainID() | 返回唯一的应用程序域标识符 |
| GetHashCode() | 返回当前线程的哈希代码 |
| GetNamedDataSlot(String) | 查找命名的数据槽.为了获取更好的性能,请改用ThreadStaticAttribute特性标记的字段 |
| Interrupt() | 中断处于WaitSleepJoin线程状态的线程 |
| Join() | 在此实例表示的线程终止前,阻止调用线程 |
| MemoryBarrier() | 按如下方式同步内存访问:执行当前线程的处理器在对指令重新排序时.不能采用先执行MemoryBarrier()调用之后的内存存取,在执行MemoryBarrier()调用之前的内存存取的方式 |
| ResetAbort() | 取消当前线程所请求的Abort(Object) |
| SetApartmentState(ApartmentState) | 在线程启动前设置其单元状态 |
| SetCompressedStack(CompressedStack) | 将捕获的CompressedStack应用到当前线程 |
| SetData | 在当前正在运行的线程上为此线程的当前域在指定槽中设置数据.为了提高性能,请改用用ThreadStaticAttribute属性标记的字段 |
| Sleep() | 将当前线程挂起指定的时间 |
| SpinWait(int iterations) | 导致线程等待由iterations参数定义的时间量 |
| Start() | 使线程得以按计划执行 |
| TrySetApartmentState(ApartmentState) | 在线程启动前设置单元状态 |
| VolatileRead() | 读取字段值 |
| VolatoleWrite() | 向字段中写入值 |
| Yield() | 导致调用线程执行准备好在当前处理器上运行的另一个线程.由操作系统选择要执行的线程 |
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(Thre));
t.Name = "t1";
t.Start();
for (int i = 0; i < 100; i++)
{
Console.Write("i");
}
}
private static void Thre()
{
for (int m = 0; m < 200; m++)
{
Console.Write("thre");
}
Console.WriteLine("正在运行的线程名字为:{0}",Thread.CurrentThread.Name);
}
控制台输出的内容是:
线程的阻塞:
如果线程的执行由于某种原因导致暂停,那么就认为该线程被阻塞了.
例如在Sleep()或通过join()等待其他线程结束.
被阻塞的线程会立即将器处理器的时间片生成给其他线程,从此就不再消耗消耗处理器时间,直到满足阻塞条件为止.
static Thread t1, t2;
static void Main(string[] args)
{
t1 = new Thread(Thre1);
t1.Name = "Thread1";
t1.Start();
t2 = new Thread(Thre1);
t2.Name = "Thread2";
t2.Start();
}
private static void Thre1()
{
for (int m = 0; m < 10; m++)
{
Console.Write("thre");
}
Console.WriteLine("正在运行的线程名字为:{0}",Thread.CurrentThread.Name);
Thread.Sleep(9000);
}
在该实例中输入t1的名字后过9秒才输出t2的名字;
可以通过ThreadState()这个属性来判断线程是否被阻塞的状态;
解除阻塞Unblocking
当遇到下列四种情况的时候,就会解除阻塞:
- 阻塞条件被满足
- 操作超时(如果设置超时的话)
- 通过Thread.Interrupt()进行打断
- 通过Thread.Abort()进行中止



