C#中ManualResetEvent怎么使用?ManualResetEvent使用方法详解

来源:Vuejs社区作者:深圳程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《C#中ManualResetEvent怎么使用?ManualResetEvent使用方法详解》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#中ManualResetEvent怎么使用?ManualResetEvent使用方法详解》有用,将其分享出去将是对创作者最好的鼓励。

ManualResetEvent是C#中System.Threading命名空间下的一个同步原语,属于WaitHandle的子类,主要用于控制多个线程的执行流程,让一个或多个线程等待某个条件的触发后再继续执行。

C#中ManualResetEvent怎么使用?ManualResetEvent使用方法详解

ManualResetEvent核心概念

ManualResetEvent内部维护一个布尔类型的状态值,这个状态值只有两种:终止状态和非终止状态。当处于终止状态时,所有调用WaitOne方法的线程都会立即返回,不会阻塞;当处于非终止状态时,调用WaitOne方法的线程会被阻塞,直到状态被设置为终止状态。

和AutoResetEvent最大的不同是,ManualResetEvent的状态需要手动重置,当状态被设置为终止后,会一直保持该状态,直到显式调用Reset方法将其重置为非终止状态,而AutoResetEvent在释放一个等待线程后会自动重置状态。

常用方法说明

  • 构造函数:ManualResetEvent(bool initialState),参数initialState表示初始状态,true为终止状态,false为非终止状态。
  • Set方法:将ManualResetEvent的状态设置为终止状态,唤醒所有正在等待的线程。
  • Reset方法:将ManualResetEvent的状态设置为非终止状态,后续调用WaitOne的线程会被阻塞。
  • WaitOne方法:阻塞当前线程,直到ManualResetEvent的状态变为终止状态,有多个重载可以设置等待超时时间。

基础使用示例

下面是一个简单的示例,主线程启动工作线程后,等待工作线程完成初始化,工作线程初始化完成后通过ManualResetEvent通知主线程继续执行。

using System;
using System.Threading;

namespace ManualResetEventDemo
{
    class Program
    {
        // 初始状态为非终止状态,工作线程需要先完成初始化
        static ManualResetEvent manualResetEvent = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            Console.WriteLine("主线程启动,开始启动工作线程");
            Thread workThread = new Thread(WorkMethod);
            workThread.Start();

            Console.WriteLine("主线程等待工作线程初始化完成");
            // 阻塞主线程,等待工作线程发出信号
            manualResetEvent.WaitOne();
            Console.WriteLine("主线程收到信号,继续执行后续逻辑");

            // 等待工作线程执行完成
            workThread.Join();
            Console.WriteLine("程序执行结束");
        }

        static void WorkMethod()
        {
            Console.WriteLine("工作线程开始执行初始化操作");
            // 模拟初始化耗时操作
            Thread.Sleep(2000);
            Console.WriteLine("工作线程初始化完成,发出信号通知主线程");
            // 将状态设置为终止状态,唤醒等待的主线程
            manualResetEvent.Set();

            // 模拟工作线程后续执行逻辑
            Thread.Sleep(1000);
            Console.WriteLine("工作线程执行完成");
        }
    }
}

多等待线程场景示例

ManualResetEvent可以唤醒多个等待的线程,下面的示例启动三个工作线程,都等待同一个ManualResetEvent的信号,当信号触发时,三个线程会同时被唤醒。

using System;
using System.Threading;

namespace ManualResetEventMultiDemo
{
    class Program
    {
        // 初始为非终止状态
        static ManualResetEvent manualResetEvent = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            Console.WriteLine("启动三个工作线程,等待信号触发");
            for (int i = 1; i <= 3; i++)
            {
                int threadId = i;
                Thread thread = new Thread(() =>
                {
                    Console.WriteLine($"工作线程{threadId}开始等待信号");
                    manualResetEvent.WaitOne();
                    Console.WriteLine($"工作线程{threadId}收到信号,开始执行任务");
                });
                thread.Start();
            }

            // 模拟主线程准备资源
            Thread.Sleep(3000);
            Console.WriteLine("主线程准备完成,触发信号唤醒所有工作线程");
            manualResetEvent.Set();

            Thread.Sleep(1000);
            Console.WriteLine("程序执行结束");
        }
    }
}

状态手动重置示例

由于ManualResetEvent的状态需要手动重置,下面的示例展示如何重复使用同一个ManualResetEvent控制多轮线程等待。

using System;
using System.Threading;

namespace ManualResetEventResetDemo
{
    class Program
    {
        static ManualResetEvent manualResetEvent = new ManualResetEvent(false);

        static void Main(string[] args)
        {
            Thread workThread = new Thread(() =>
            {
                for (int i = 1; i <= 3; i++)
                {
                    Console.WriteLine($"工作线程等待第{i}轮信号");
                    manualResetEvent.WaitOne();
                    Console.WriteLine($"工作线程收到第{i}轮信号,执行第{i}轮任务");
                    // 执行完任务后,重置状态,等待下一轮信号
                    manualResetEvent.Reset();
                }
            });
            workThread.Start();

            // 触发三轮信号
            for (int i = 1; i <= 3; i++)
            {
                Thread.Sleep(2000);
                Console.WriteLine($"主线程触发第{i}轮信号");
                manualResetEvent.Set();
            }

            workThread.Join();
            Console.WriteLine("程序执行结束");
        }
    }
}

使用注意事项

  • ManualResetEvent使用完成后需要实现IDisposable接口释放资源,建议使用using语句包裹,避免资源泄漏。
  • 如果初始状态设置为true,那么第一个调用WaitOne的线程不会被阻塞,会直接通过。
  • 调用Set方法后,状态会一直保持终止,直到调用Reset,所以如果有需要重复等待的场景,一定要记得调用Reset方法。
  • WaitOne方法可以设置超时时间,如果超时后状态仍未变为终止,方法会返回false,实际使用中可以根据返回值判断等待是否成功。

ManualResetEvent和AutoResetEvent对比

对比项ManualResetEventAutoResetEvent
状态重置方式手动调用Reset方法重置释放一个等待线程后自动重置
唤醒线程数量可以唤醒所有等待的线程每次只能唤醒一个等待的线程
适用场景需要通知多个线程同时开始执行,或者需要重复控制多轮等待的场景需要逐个唤醒等待线程,控制线程依次执行的场景

实际应用场景

ManualResetEvent常见的应用场景包括:多个工作线程等待主线程的资源初始化完成后同时开始工作、控制线程池中的线程分批执行任务、实现线程的暂停和恢复功能等。在需要多个线程同步等待同一个条件的场景中,ManualResetEvent是非常合适的选择。

ManualResetEventC#线程同步WaitHandle修改时间:2026-07-12 18:00:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。