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();
相关推荐
步步为营DotNet2 小时前
深度解析C# 11的Required成员:编译期验证保障数据完整性
java·前端·c#
武藤一雄4 小时前
C# 语法糖详解
后端·microsoft·c#·.net
武藤一雄4 小时前
C#:进程/线程/多线程/AppDomain详解
后端·微软·c#·asp.net·.net·wpf·.netcore
曹牧5 小时前
在C#中,string和String
开发语言·c#
小菱形_6 小时前
【C#】LINQ
开发语言·c#·linq
曹牧7 小时前
C#:foreach
开发语言·c#
曹牧7 小时前
C#中解析JSON数组
开发语言·c#·json
武藤一雄9 小时前
C#:Linq大赏
windows·后端·microsoft·c#·.net·.netcore·linq
@年年9 小时前
C#十字线小工具
c#