ManualResetEvent和AutoResetEvent

这篇具有很好参考价值的文章主要介绍了ManualResetEvent和AutoResetEvent。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、 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.");
}

ManualResetEvent和AutoResetEvent

打印 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.");
}

ManualResetEvent和AutoResetEvent

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

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

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

三、AutoResetEvent和ManualResetEvent的异同文章来源地址https://www.toymoban.com/news/detail-673388.html

AutoResetEvent和ManualResetEvent都是.NET Framework中的同步原语,用于协调多个线程的执行。它们的主要区别在于:
1. 触发方式
  • AutoResetEvent:当某个线程调用Set方法时,只有一个等待的线程会被唤醒,并被允许继续执行。如果有多个线程等待,那么只有其中一个会被唤醒,其他线程仍然处于等待状态。
  • ManualResetEvent:当某个线程调用Set方法时,所有等待的线程都会被唤醒,并被允许继续执行。
2. 重置方式
  • AutoResetEvent:当某个线程被唤醒后,事件会自动重置为未触发状态,其他等待的线程需要重新等待。
  • ManualResetEvent:当某个线程被唤醒后,事件仍然处于触发状态,其他等待的线程仍然可以通过WaitOne方法获取事件的信号。
3. 使用场景
  • AutoResetEvent:适用于需要严格控制线程执行顺序的情况,例如生产者-消费者模式中的消费者线程需要等待生产者线程完成后才能执行。
  • ManualResetEvent:适用于需要多个线程同时执行的情况,例如并行计算中的多个线程需要等待某个条件满足后才能继续执行。
总的来说,AutoResetEvent更适合用于线程间的协作,而ManualResetEvent更适合用于线程池等多线程并发执行的场景。

到了这里,关于ManualResetEvent和AutoResetEvent的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 根据一个List生成另外一个List,修改其中一个,导致另外一个List也在变化

    1、两个List复制         SysDic aSysDic = new SysDic();         aSysDic.setDkey(\\\"1\\\");         aSysDic.setDnote(\\\"12\\\");         SysDic bSysDic = new SysDic();         bSysDic.setDkey(\\\"2\\\");         bSysDic.setDnote(\\\"23\\\");         SysDic cSysDic = new SysDic();         cSysDic.setDkey(\\\"3\\\");         cSysDic.setDnote(\\\"34\\\");  

    2024年02月10日
    浏览(39)
  • 将一个硬盘空间分配给另一个硬盘,怎么把一个磁盘的空间给另一个磁盘

    用户在管理电脑磁盘分区的时候,为了更好地利用磁盘分区,需要对磁盘分区进行调整,如果涉及到磁盘分区调整, 将一个硬盘空间分配给另一个硬盘 ?那么,在本文中,易我小编将介绍电脑磁盘分区调整的知识,并且介绍两种很实用的磁盘重新分区的方法。 在Windows系统中

    2024年02月06日
    浏览(52)
  • matlab中令一个矩阵中的一个区域等于另一个矩阵

    在MATLAB中,你可以使用矩阵索引来将一个矩阵中的一个区域设置为另一个矩阵。假设你有两个矩阵A和B,你想将A中的一部分替换为B。以下是实现此操作的一种方法: 在这个例子中,我们使用了矩阵索引来选择A中的一个子矩阵。A(2:4,2:4)选择了A的第二行到第四行、第二列到第

    2024年02月12日
    浏览(35)
  • 一个数组是否包含另一个数组

    //两个数组对象中查看 其中一个数组对象是否包含另一个数组对象中的值 let arr = [ {key:1,val:\\\"张胜男\\\"}, {key:2,val:\\\"王五\\\"}, {key:3,val:\\\"李四\\\"}, {key:4,val:\\\"刘超\\\"}, {key:5,val:\\\"赵四\\\"} ] let arr2 = [ {key:1,val:\\\"张胜男\\\"}, {key:2,val:\\\"王五\\\"}, {key:6,val:\\\"666\\\"}, {key:7,val:\\\"777\\\"}, {key:8,val:\\\"888\\\"}, {key:9,val:\\\"999\\\"}, ]

    2024年02月09日
    浏览(45)
  • 【点击新增一个下拉框 与前一个内容一样 但不能选同一个值】

    主要是看下拉选择el-option的disabled,注意不要混淆 methods:

    2024年02月11日
    浏览(60)
  • 单例模式:保证一个类只有一个实例

    在软件开发中,有些类 只需要一个实例 ,比如数据库连接池、线程池等。单例模式就是一种设计模式,用于 确保一个类只有一个实例,并提供一个全局访问点 。 1. 饿汉式 饿汉式是最简单的实现方式,它在类加载时就创建了实例,并且提供一个静态方法返回该实例。 jdk源码

    2024年02月14日
    浏览(41)
  • Linux如何将一个目录移动到另一个目录去,Linux 中,可以使用 mv 命令将一个目录移动到另一个目录中。

    在 Linux 中,可以使用 mv 命令将一个目录移动到另一个目录中。 命令格式如下: 其中,选项包括: -f :覆盖目标文件(不提示)。 -i :询问是否覆盖目标文件。 -n :不覆盖任何已存在的目标文件。 -v :显示移动的详细过程。 例如,将目录 /home/user1/documents 移动到 /home/use

    2024年02月08日
    浏览(86)
  • 一个简单的Web程序(详解创建一个Flask项目后自带的一个简单的Web程序)

    程序代码截图如下:  在创建 Flask 程序时,通常需要先创建一个应用实例进行应用初始化。 上述代码中,使用 Flask 类创建了一个应用实例 app。 __name__ 参数用于获取当前代码文件的文件名,作为应用实例的名称。 if __name__ == \\\'__main__\\\': app.run(debug=True) 用于启动服务器并运行应

    2024年01月20日
    浏览(50)
  • c# 判断一个字符串列表是否包含另一个字符串列表中某一个元素

    当需要判断一个字符串列表是否包含另一个字符串列表中的某个元素时,可以使用 LINQ 查询来完成。下面是一个示例方法: 在上面的示例中,我们有两个字符串列表 list1 和 list2。我们想要判断 list1 是否包含了 list2 中的某个元素。 我们定义了 ListContainsElement 方法,该方法接

    2024年02月12日
    浏览(83)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包