C# ManualResetEvent

2023-09-19 16:31:04 浏览数 (1)

1.概要

ManualResetEvent 用于在多个线程之间进行通信。它可以控制线程的执行顺序和时间,使得一个或多个线程等待某个条件成立(或者说事件发生)

主要特点:

  1. 两种状态ManualResetEvent具有两种状态 - 信号和非信号。调用 Set() 方法将事件设置为信号状态,调用 Reset() 方法将事件设置为非信号状态。
  2. 阻塞或释放多个线程:在事件为非信号状态时,调用 WaitOne() 方法的线程将被阻塞。当事件转换为信号状态时,所有等待该事件的线程都将继续执行。
  3. 手动重置:与 AutoResetEvent 不同,ManualResetEvent 不会在释放一个等待的线程后自动重置为非信号状态。相反,它会保持信号状态,直到明确调用 Reset() 方法。
  4. 跨线程通信ManualResetEvent 可以用于不同线程之间的通信。一个线程可以等待一个事件,而另一个线程可以设置或重置该事件。
  5. 简单易用ManualResetEvent 类的 API 非常简单直接,只需要几个方法就能实现线程间的有效同步。
  6. 线程池兼容ManualResetEvent 可以与 .NET 的线程池 (ThreadPool) 结合使用,以便更有效地管理和控制线程资源。
优点
  1. 线程同步ManualResetEvent 提供了一种有效的方式来同步多个线程。你可以使用它来确保一个或多个线程在其他工作完成之前不会继续进行。
  2. 灵活性:与 AutoResetEvent 相比,ManualResetEvent 允许多个等待的线程在事件被设为信号状态后同时继续进行。这是因为 ManualResetEvent 在被手动重置之前会保持信号状态,而 AutoResetEvent 在释放一个等待的线程后会自动回到非信号状态。
缺点
  1. 手动控制ManualResetEvent 需要手动重置,这可能会导致错误,例如如果忘记重置事件,那么所有调用 WaitOne() 的线程将立即继续执行,即使预期应该阻塞他们。
  2. 无法传递额外信息ManualResetEvent 只提供二元(信号/非信号)的同步机制,并不能传递更为复杂的状态信息。对于需要传递更多数据或状态信息的场景,可能需要使用更为复杂的同步结构如 Monitor, Mutex, Semaphore 等。

2.详细内容

代码语言:javascript复制
using System;
using System.Threading;

class Program
{
    private static ManualResetEvent manualEvent = new ManualResetEvent(false);

    static void Main(string[] args)
    {
        Thread thread1 = new Thread(ThreadProc);
        thread1.Name = "Thread1";
        thread1.Start();

        Thread thread2 = new Thread(ThreadProc);
        thread2.Name = "Thread2";
        thread2.Start();

        Console.WriteLine("Waiting for threads to complete.");
        manualEvent.Set();  // Signal that work can be done.
        thread1.Join();
        thread2.Join();

        Console.WriteLine("All threads have completed.");
    }

    static void ThreadProc()
    {
        string name = Thread.CurrentThread.Name;

        Console.WriteLine($"{name} waits on ManualResetEvent.");
        manualEvent.WaitOne();  // Wait for the signal.
        Console.WriteLine($"{name} receives a signal to proceed.");
        // Do some work...
    }
}

0 人点赞