ManualResetEvent和AutoResetEvent
  4CCAvn5kOf6A 2023年11月02日 49 0
一、 ManualResetEvent
ManualResetEvent是一个同步对象,可以使一个或多个线程等待另一个线程的信号,然后再同时继续执行。它是通过两个状态来实现的:有信号和无信号。
以下是ManualResetEvent的各个方法的介绍:
  • Set方法:将ManualResetEvent的状态设置为有信号,允许等待线程继续执行。如果没有线程在等待,该方法不会产生任何效果。
  • Reset方法:将ManualResetEvent的状态设置为无信号,阻止等待线程继续执行。如果没有线程在等待,该方法不会产生任何效果。
  • WaitOne方法:阻塞当前线程,等待ManualResetEvent的状态变为有信号。如果ManualResetEvent的状态已经是有信号,该方法立即返回。
  • WaitOne方法(带超时参数):阻塞当前线程,等待ManualResetEvent的状态变为有信号,或者超过指定的时间。如果ManualResetEvent的状态已经是有信号,该方法立即返回。
  • WaitAll方法(静态方法):阻塞当前线程,等待所有指定的ManualResetEvent的状态变为有信号。如果所有指定的ManualResetEvent的状态已经是有信号,该方法立即返回。
  • WaitAny方法(静态方法):阻塞当前线程,等待任意一个指定的ManualResetEvent的状态变为有信号。如果任意一个指定的ManualResetEvent的状态已经是有信号,该方法立即返回。
  • Dispose方法:释放由ManualResetEvent占用的所有资源。一旦调用该方法,ManualResetEvent就不再可用。
static ManualResetEvent mre = new ManualResetEvent(false);//创建了一个ManualResetEvent对象,并将初始状态设置为无信号状态
static void Main(string[] args)
{
    //启动一个线程,等待信号
    Thread thread = new Thread(new ThreadStart(WaitForSignal));
    thread.Start();

    //暂停一秒钟
    Thread.Sleep(1000);

    //发送信号
    Console.WriteLine("Sending signal...");
    mre.Set();  //将ManualResetEvent的状态设置为有信号,允许等待线程继续执行。如果没有线程在等待,该方法不会产生任何效果。

    // 暂停一秒钟
    Thread.Sleep(1000);

    // 再次发送信号
    Console.WriteLine("Sending signal again...");
    mre.Set();

    //等待线程完成
    thread.Join();

    Console.WriteLine("Done");
    Console.ReadKey();
}

private static void WaitForSignal()
{
    Console.WriteLine("Waiting for signal...");
    mre.WaitOne();  //阻塞当前线程,等待ManualResetEvent的状态变为有信号。如果ManualResetEvent的状态已经是有信号,该方法立即返回。
    Console.WriteLine("Signal received.");
    Console.WriteLine("Waiting for signal again...");
    mre.Reset();    //将ManualResetEvent的状态设置为无信号,阻止等待线程继续执行。如果没有线程在等待,该方法不会产生任何效果。
    mre.WaitOne();
    Console.WriteLine("Signal received again.");
}

打印 Waiting for signal...后等待1s,

打印 Waiting for signal again...后等待1s.

 

二、AutoResetEvent

AutoResetEvent是一种同步机制,用于线程之间的通信。它允许一个线程等待另一个线程发出信号,然后继续执行。AutoResetEvent只能被一个线程等待,当一个线程调用WaitOne方法时,AutoResetEvent会被设置为非终止状态,直到另一个线程调用Set方法将其设置为终止状态。
以下是AutoResetEvent的各个方法的介绍:
  • WaitOne()方法:该方法会阻塞当前线程,直到AutoResetEvent对象的状态为终止状态(signaled),或等待超时。如果成功等待到终止状态,则会将AutoResetEvent对象的状态设置为非终止状态(nonsignaled)。
  • Set()方法:该方法将AutoResetEvent对象的状态设置为终止状态。如果有线程正在等待这个AutoResetEvent对象,则会使其中一个线程从WaitOne()方法中返回。
  • Reset()方法:该方法将AutoResetEvent对象的状态设置为非终止状态。如果有线程正在等待这个AutoResetEvent对象,则不会有任何影响,等待线程仍然会等待。
  • Dispose()方法:该方法释放AutoResetEvent对象占用的资源,并将AutoResetEvent对象标记为已释放。一旦AutoResetEvent对象被释放,任何对它的方法调用都会引发ObjectDisposedException异常。

 

static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
    //启动一个线程,等待信号
    Thread thread = new Thread(new ThreadStart(WaitForSignal));
    thread.Start();

    //暂停一秒钟
    Thread.Sleep(10000);

    //发送信号
    Console.WriteLine("Sending signal...");
    autoResetEvent.Set();  //该方法将AutoResetEvent对象的状态设置为终止状态。如果有线程正在等待这个AutoResetEvent对象,则会使其中一个线程从WaitOne()方法中返回。

    // 暂停一秒钟
    Thread.Sleep(10000);

    // 再次发送信号
    Console.WriteLine("Sending signal again...");
    autoResetEvent.Set();

    //等待线程完成
    thread.Join();

    Console.WriteLine("Done");
    Console.ReadKey();
}

private static void WaitForSignal()
{
    Console.WriteLine("Waiting for signal...");
    autoResetEvent.WaitOne();  //该方法会阻塞当前线程,直到AutoResetEvent对象的状态为终止状态(signaled),或等待超时。如果成功等待到终止状态,则会将AutoResetEvent对象的状态设置为非终止状态(nonsignaled)。
    Console.WriteLine("Signal received.");
    Console.WriteLine("Waiting for signal again...");
    autoResetEvent.WaitOne();
    Console.WriteLine("Signal received again.");
}

打印 Waiting for signal...后等待1s,

打印 Waiting for signal again...后等待1s.

注意: 不需要调用Reset方法去将AutoResetEvent对象的状态设置为非终止状态,WaitOne方法等待Set方法将AutoResetEvent对象的状态设置为终止状态后,会将AutoResetEvent对象的状态设置为非终止状态,即再次等待Set方法。

三、AutoResetEvent和ManualResetEvent的异同

AutoResetEvent和ManualResetEvent都是.NET Framework中的同步原语,用于协调多个线程的执行。它们的主要区别在于:
1. 触发方式
  • AutoResetEvent:当某个线程调用Set方法时,只有一个等待的线程会被唤醒,并被允许继续执行。如果有多个线程等待,那么只有其中一个会被唤醒,其他线程仍然处于等待状态。
  • ManualResetEvent:当某个线程调用Set方法时,所有等待的线程都会被唤醒,并被允许继续执行。
2. 重置方式
  • AutoResetEvent:当某个线程被唤醒后,事件会自动重置为未触发状态,其他等待的线程需要重新等待。
  • ManualResetEvent:当某个线程被唤醒后,事件仍然处于触发状态,其他等待的线程仍然可以通过WaitOne方法获取事件的信号。
3. 使用场景
  • AutoResetEvent:适用于需要严格控制线程执行顺序的情况,例如生产者-消费者模式中的消费者线程需要等待生产者线程完成后才能执行。
  • ManualResetEvent:适用于需要多个线程同时执行的情况,例如并行计算中的多个线程需要等待某个条件满足后才能继续执行。
总的来说,AutoResetEvent更适合用于线程间的协作,而ManualResetEvent更适合用于线程池等多线程并发执行的场景。
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  NPQODODLqddb   2024年05月17日   70   0   0 .NET
  mVIyUuLhKsxa   2024年05月17日   53   0   0 .NET
  XkHDHG7Y62UM   2024年05月17日   45   0   0 .NET
  f18CFixvrKz8   2024年05月18日   88   0   0 .NET
  rBgzkhl6abbw   2024年05月18日   78   0   0 .NET
  MYrYhn3ObP4r   2024年05月17日   41   0   0 .NET
  S34pIcuyyIVd   2024年05月17日   60   0   0 .NET
  gKJ2xtp6I8Y7   2024年05月17日   50   0   0 .NET
  MYrYhn3ObP4r   2024年05月17日   40   0   0 .NET
4CCAvn5kOf6A