当前位置:首页 > C# > 正文

深入理解C#线程同步机制(AutoResetEvent与ManualResetEvent详解)

在多线程编程中,线程之间的协调与同步至关重要。C# 提供了多种同步原语来帮助开发者控制线程的执行顺序和状态。AutoResetEventManualResetEvent 是 .NET 中两个非常常用的线程同步事件对象,它们都继承自 WaitHandle 类,用于在多个线程之间传递信号。本文将用通俗易懂的方式,带你彻底搞懂这两个类的区别、使用场景及实际代码示例。

深入理解C#线程同步机制(AutoResetEvent与ManualResetEvent详解) C# AutoResetEvent  ManualResetEvent 线程同步事件 .NET线程控制 第1张

什么是 AutoResetEvent?

AutoResetEvent(自动重置事件)是一种线程同步机制。当一个线程调用 Set() 方法时,它会释放一个正在等待的线程(如果有的话),然后自动将状态重置为非触发(即“关闭”状态)。你可以把它想象成一个“单次通行门”:打开一次,只允许一个人通过,然后自动关上。

AutoResetEvent 使用示例

using System;using System.Threading;class Program{    static AutoResetEvent autoEvent = new AutoResetEvent(false);    static void Main()    {        // 启动一个工作线程        Thread worker = new Thread(DoWork);        worker.Start();        Console.WriteLine("主线程:等待3秒后发出信号...");        Thread.Sleep(3000);        // 发出信号,唤醒等待的线程        autoEvent.Set();        worker.Join();        Console.WriteLine("主线程:程序结束。");    }    static void DoWork()    {        Console.WriteLine("工作线程:开始工作,等待信号...");        autoEvent.WaitOne(); // 阻塞,直到收到信号        Console.WriteLine("工作线程:收到信号,继续执行!");    }}

运行上述代码,你会看到工作线程在主线程调用 Set() 后才继续执行。这就是 C# AutoResetEvent 的典型应用场景。

什么是 ManualResetEvent?

AutoResetEvent 不同,ManualResetEvent(手动重置事件)在调用 Set() 后会保持“打开”状态,直到显式调用 Reset() 方法将其关闭。这意味着它可以同时唤醒WaitOne() 的线程也不会被阻塞(因为事件仍处于触发状态)。

ManualResetEvent 使用示例

using System;using System.Threading;class Program{    static ManualResetEvent manualEvent = new ManualResetEvent(false);    static void Main()    {        // 启动两个工作线程        Thread t1 = new Thread(Worker);        Thread t2 = new Thread(Worker);        t1.Start("线程A");        t2.Start("线程B");        Console.WriteLine("主线程:5秒后发出全局信号...");        Thread.Sleep(5000);        manualEvent.Set(); // 打开闸门,所有等待线程通过        t1.Join();        t2.Join();        Console.WriteLine("主线程:所有线程完成。");    }    static void Worker(object name)    {        string threadName = (string)name;        Console.WriteLine($"{threadName}:等待全局信号...");        manualEvent.WaitOne();        Console.WriteLine($"{threadName}:收到信号,开始工作!");    }}

在这个例子中,两个线程都会在 manualEvent.Set() 被调用后立即继续执行。这体现了 C# ManualResetEvent 的“广播”特性。

核心区别总结

  • AutoResetEvent:调用 Set() 后仅释放一个等待线程,然后自动重置为非信号状态。
  • ManualResetEvent:调用 Set() 后释放所有等待线程,并保持信号状态,直到调用 Reset() 手动关闭。

如何选择?

- 如果你只需要唤醒一个线程(例如生产者-消费者模型中的单个消费者),使用 AutoResetEvent
- 如果你需要一次性唤醒多个线程(例如启动一批任务、初始化完成通知等),使用 ManualResetEvent

此外,在现代 .NET 开发中,你也可以考虑使用更高级的同步工具,如 TaskCompletionSourceCountdownEventBarrier,但在理解底层机制时,掌握 .NET线程控制 的基础——包括 AutoResetEventManualResetEvent——仍然非常重要。

结语

通过本文,你应该已经掌握了 C# AutoResetEventC# ManualResetEvent 的核心概念、使用方法和适用场景。记住:正确的线程同步是构建高性能、无死锁应用程序的关键。希望这篇教程能帮助你在 .NET线程控制 的道路上更进一步!

关键词回顾:C# AutoResetEvent, C# ManualResetEvent, 线程同步事件, .NET线程控制