当前位置: 首页 > article >正文

c# WaitSleepJoin状态的线程如何自动恢复

在 C# 中,线程的 ThreadState.WaitSleepJoin 状态表示线程当前处于等待、睡眠或加入(比如等待锁、等待事件、或者调用 Thread.Sleep 等)。要让一个处于 WaitSleepJoin 状态的线程恢复运行,必须唤醒它或让它不再被阻塞。这通常通过以下几种方式实现:

1. 使用 Monitor.PulseMonitor.PulseAll

如果线程因为 Monitor.Waitlock 等机制而进入等待状态,可以使用 Monitor.PulseMonitor.PulseAll 来唤醒一个或所有等待的线程。

示例:使用 Monitor 来管理线程的等待和唤醒
using System;
using System.Threading;

class Program
{
    private static object _lock = new object();
    
    static void Main()
    {
        Thread thread = new Thread(WaitingThread);
        thread.Start();

        // 主线程睡眠 1 秒钟,然后唤醒等待线程
        Thread.Sleep(1000);
        lock (_lock)
        {
            Console.WriteLine("主线程正在唤醒等待线程");
            Monitor.Pulse(_lock); // 唤醒一个等待线程
        }

        thread.Join(); // 等待子线程结束
    }

    static void WaitingThread()
    {
        lock (_lock)
        {
            Console.WriteLine("等待线程正在等待...");
            Monitor.Wait(_lock); // 使线程进入等待状态
            Console.WriteLine("等待线程被唤醒");
        }
    }
}

在上述代码中,WaitingThread 线程调用 Monitor.Wait 进入 WaitSleepJoin 状态,主线程通过 Monitor.Pulse 唤醒它,恢复线程执行。

2. 使用 ManualResetEventAutoResetEvent

ManualResetEventAutoResetEvent 是两种常用的同步事件,它们可以用于线程间的协调。你可以使用这些类的 Set 方法来唤醒一个或多个等待线程。

  • AutoResetEvent:每次唤醒一个等待线程后,会自动重置为无信号状态。
  • ManualResetEvent:唤醒后需要手动重置,直到调用 Reset
示例:使用 AutoResetEvent
using System;
using System.Threading;

class Program
{
    private static AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

    static void Main()
    {
        Thread thread = new Thread(WaitingThread);
        thread.Start();

        // 主线程睡眠 1 秒钟,然后唤醒等待线程
        Thread.Sleep(1000);
        Console.WriteLine("主线程正在唤醒等待线程");
        _autoResetEvent.Set(); // 唤醒等待线程

        thread.Join(); // 等待子线程结束
    }

    static void WaitingThread()
    {
        Console.WriteLine("等待线程正在等待...");
        _autoResetEvent.WaitOne(); // 线程在此等待直到被唤醒
        Console.WriteLine("等待线程被唤醒");
    }
}

在上述代码中,WaitingThread 线程调用 _autoResetEvent.WaitOne() 进入等待状态,主线程通过调用 _autoResetEvent.Set() 唤醒它。

3. 使用 Thread.Sleep

如果线程处于 Thread.Sleep 状态(也是 WaitSleepJoin 状态的一种),它会在设定的时间到达后自动恢复。调用 Thread.Sleep 后的线程会在指定的时间过后继续执行,自动恢复。

示例:使用 Thread.Sleep
using System;
using System.Threading;

class Program
{
    static void Main()
    {
        Thread thread = new Thread(WaitingThread);
        thread.Start();

        // 主线程睡眠 1 秒钟
        Thread.Sleep(1000);

        thread.Join(); // 等待子线程结束
    }

    static void WaitingThread()
    {
        Console.WriteLine("等待线程正在睡眠...");
        Thread.Sleep(2000); // 线程睡眠 2 秒
        Console.WriteLine("等待线程被唤醒");
    }
}

在上述代码中,WaitingThread 线程调用 Thread.Sleep(2000) 进入等待状态。线程会在 2 秒后自动恢复并继续执行。

4. 使用 Task 类的异步操作

在现代 C# 开发中,使用 Taskasync/await 模式来处理线程等待和恢复是更常见的做法。Task.Delay 使得线程可以在异步等待期间不阻塞主线程。

示例:使用 Task.Delay(异步)
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        Task task = WaitingTask();

        // 主线程继续执行其他操作
        await Task.Delay(1000); // 主线程延时 1 秒

        await task; // 等待任务完成
    }

    static async Task WaitingTask()
    {
        Console.WriteLine("等待任务正在等待...");
        await Task.Delay(2000); // 异步等待 2 秒
        Console.WriteLine("等待任务被唤醒");
    }
}

在此代码中,WaitingTask 异步任务使用 Task.Delay(2000) 进入等待状态,自动恢复。

总结

要让处于 WaitSleepJoin 状态的线程恢复,可以根据实际情况选择不同的同步机制:

  1. 使用 Monitor.PulseMonitor.PulseAll:用于 lock 语句块中,通过唤醒等待的线程。
  2. 使用 AutoResetEventManualResetEvent:线程等待这些事件的信号来恢复。
  3. 使用 Thread.Sleep:线程会在指定时间后自动恢复执行。
  4. 使用 Task.Delay:异步任务会在指定时间后自动恢复。

通常,现代 C# 开发推荐使用 Taskasync/await 模式来避免复杂的线程管理。


http://www.kler.cn/a/458484.html

相关文章:

  • 案例分析-采样率对模拟链路的带宽的影响
  • C语言宏和结构体的使用代码
  • 【游戏设计原理】41 - 游戏的核心
  • leetcode 3219. 切蛋糕的最小总开销 II
  • 【最新】17个一站式数据集成平台案例PPT下载(Apache SeaTunnel )
  • HarmonyOS开发:关于帧动画使用分享
  • ArcGIS计算矢量要素集中每一个面的遥感影像平均值、最大值等统计指标
  • 改变HTML元素的方式有哪些?如何在HTML中添加/替换或删除元素?
  • 微服务保护-sentinel
  • 大模型-Ollama使用相关的笔记
  • 网络:常用的以太网PHY芯片
  • Shader数学基础16-齐次除法
  • sql group by 多个字段例子
  • 《2023-2024网络安全产业发展核心洞察与趋势预测》
  • 使用PyTorch进行自动微分
  • Effective C++ 条款 20:宁以 pass-by-reference-to-const 替换 pass-by-value
  • C++ 设计模式:单例模式(Singleton Pattern)
  • 如何使用爬虫工具Selenium
  • 腾讯PHP经典面试题(附答案)
  • zookeeper+kafka的windows下安装
  • 【服务器项目部署】⭐️将本地项目部署到服务器!
  • 鸿蒙项目云捐助第二十七讲云捐助项目首页分类导航的联动效果
  • go下载依赖提示连接失败
  • 农家乐系统|Java|SSM|VUE| 前后端分离
  • Flink状态编程
  • C++运算符重载实例