1.10 线程其他操作

1.线程状态

2.自旋

3.线程暂停

4.线程返回结果

5.取消线程

6.线程捕获异常


1.线程状态

csharp 复制代码
a.定义线程但未启动时, 线程状态: "UnStarted"

b.运行时线程状态: "Running"

c.线程被阻塞(可能是Sleep, Join, 请求锁时), 线程状态: "WaitSleepJoin"; 一旦线程处于此状态时, 线程调度器将线程

踢出

d.线程处于停止状态: "Stop"

2.自旋

csharp 复制代码
你和朋友约定在某个地点见面, 但你不知道朋友什么时候到; 你有两种策略:

a.站在原地, 不停地四处张望, 看看朋友有没有来, 这就是自旋

b.坐在旁边的长椅上, 闭上眼睛休息, 每隔一段时间(比如5分钟)睁开眼睛看一下, 这就是睡眠等待(Sleep)
csharp 复制代码
自旋等待(Spinning)的伪代码

while (条件不满足) {
// 什么也不做, 或者执行一些空操作(比如执行一些特殊的CPU指令, 如pause)
}

这个循环会一直执行, 直到条件满足; 在这个过程中, 线程不会被挂起, 它一直占用着CPU
csharp 复制代码
为什么需要自旋呢?

因为线程的睡眠和唤醒(即上下文切换)是有开销的, 如果等待的时间非常短, 那么让线程睡眠再唤醒的总开销可能比自旋等待

的开销还要大; "自旋适用于等待时间非常短的场景"

但是, 自旋有一个很大的缺点: 如果等待时间很长, 那么自旋就会浪费大量的CPU时间, 因为线程一直在占用CPU做无用的检

查

3.线程暂停

csharp 复制代码
1).Thread.Sleep

a.作用: 让当前线程休眠指定的时间, 期间线程会让出CPU, 进入等待状态, 允许其他线程允许

b.特点:

- 休眠期间线程处于"阻塞状态", 不消耗CPU资源

- 休眠时间到了, 线程就进入就绪状态, 等待调度

- 由于上下文切换, 可能会有一定的开销

c.示例
csharp 复制代码
2).Thread.SpinWait

a.作用: 让当前线程进行自旋等待, 线程不会让出CPU, 而是在一个循环中不断检查条件(忙等待)

b.特点: 

- 参数iterations是自旋的次数

- 自旋期间线程不会放弃CPU, 因此不涉及上下文切换, 但浪费CPU周期

- 适用于等待时间极短的情况

c.示例
csharp 复制代码
3).SpainWait.SpainUntil

a.作用: 自旋等待直到某个条件成立或超时

b.特点:

- 在条件满足或超时之前, 会混合使用自旋和真正的休眠(以减少CPU占用)

- 返回值为true表示条件在超时前满足, 否则为false

- 适用于条件可能在短时间内满足的等待场景

4.线程返回结果

csharp 复制代码
Thread中无内置的方法返回结果, 返回结果的唯一方法是共享变量
csharp 复制代码
class Program
{
	private static string result;
	
	static void Main(string[] args)
	{
	    Thread thread = new Thread(() => {
	        Worker();
	    });
	    thread.Start();
	    thread.Join();
	
	    Console.WriteLine(result);
	}
	
	private static void Worker()
	{
	    result = "Show Result";
	}
}

5.取消线程

csharp 复制代码
1).通过一个共享变量来取消线程

volatile 的好处: "让线程之间看得见彼此对变量的修改,并且不乱排顺序,性能接近普通变量但比锁快得多"
csharp 复制代码
class Program
{
	// 控制线程是否被取消
	// volatile 保证线程从内存中读取最新的值
	// 适用于一个线程写 一个线程读
	private static volatile bool cancelThread;
	
	static void Main(string[] args)
	{
	    Thread thread = new Thread(() => {
	        Worker();
	    });
	    thread.Start();
	    Console.ReadLine();
	
	    cancelThread = true;
	}
	
	private static void Worker()
	{
	    while (cancelThread) 
	    {
	        Thread.Sleep(1000);
	    }
	}
}

csharp 复制代码
2).CancellationToken 来取消任务
csharp 复制代码
class Program
{
    private static CancellationTokenSource cts = new CancellationTokenSource();

    static void Main(string[] args)
    {
        Thread thread = new Thread(() => Worker(cts.Token));
        thread.Start();

        Console.ReadLine();
        cts.Cancel(); // 发送取消信号

        thread.Join();
    }

    private static void Worker(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            Console.WriteLine("Working...");
            Thread.Sleep(1000);
        }
    }
}

6.线程捕获异常

csharp 复制代码
a."工作线程出现异常, 不会传播到调用线程"

比如: 主线程中启动工作线程, 工作线程出现异常, 主线程无法捕获

b.处理线程的异常, 则需在线程内使用try catch即可
csharp 复制代码
Thread thread = new Thread(() =>
{
    try
    {
        // 工作代码
    }
    catch (Exception ex)
    {
        // 处理异常
        Console.WriteLine($"线程异常:{ex.Message}");
        // 考虑如何通知主线程
    }
    finally
    {
        // 清理资源
    }
});
thread.Start();
相关推荐
CoderIsArt10 小时前
C#中UI 线程与 Dispatcher
开发语言·ui·c#
呆呆敲代码的小Y1 天前
【游戏开发】Lua 与 C# 交互原理解析
c#·lua·交互·热更新·lua与c#交互·游戏热更新
用户298698530141 天前
PDF 转纯文本(TXT)免费攻略:轻松提取文字内容
人工智能·后端·c#
呆呆敲代码的小Y1 天前
【游戏开发】C# 中的迭代器
java·开发语言·c#·迭代器
格林威2 天前
C# 相机Burst模式图像采集:使用相机内存配合OpenCvSharp和Halcon实现短时间的高速采集的方法
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
J总裁的小芒果2 天前
参数过多-分批传参
c#
典典分享指南2 天前
短视频分镜提示词:让 AI 出片的产品口播
java·c#·bash·composer·symfony
Z5998178412 天前
c#软件开发学习笔记--WPF(Canvas、数据绑定、MVVM模式、值转换器)
笔记·学习·c#
淡海水2 天前
05-03-栈队列-PriorityQueue-TElement-TPriority-NET6优先队列语义与四叉堆实现
服务器·前端·c#·priorityqueue·clr·telement