C# | 使用AutoResetEvent和ManualResetEvent进行线程同步和通信

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


使用AutoResetEvent和ManualResetEvent进行线程同步和通信
文章目录
使用AutoResetEvent和ManualResetEvent进行线程同步和通信
介绍
AutoResetEvent
ManualResetEvent
异同点
使用场景和代码示例
AutoResetEvent 使用示例
ManualResetEvent 使用示例
阻塞多个线程并同时激活


介绍
在多线程编程中,AutoResetEvent 和 ManualResetEvent 是两个常用的同步原语。它们用于线程间的通信和协调,以确保线程按照特定的顺序执行。本篇博客将介绍这两种同步原语的概念、用法和区别。

AutoResetEvent
AutoResetEvent (自动重置事件)是一个同步基元,它允许一个线程等待其他线程在信号状态之前进行等待,用于在线程间提供简单的信号通知机制。它的工作方式是,当一个线程通过调用 WaitOne() 方法等待事件信号时,如果事件处于非终止状态,线程将被阻塞。当另一个线程调用 Set() 方法将事件设置为终止状态时,等待的线程将被唤醒,并且事件将自动重置为非终止状态。

ManualResetEvent
ManualResetEvent (手动重置事件)也是一个同步基元,它与AutoResetEvent类似,也用于在线程间提供信号通知机制。与 AutoResetEvent 不同的是,ManualResetEvent 在设置为终止状态后,会一直保持终止状态,直到调用 Reset() 方法将其重置为非终止状态。另外,它允许所有等待的线程在同一个信号状态下被唤醒。当一个线程通过调用 WaitOne() 方法等待事件信号时,如果事件处于非终止状态,线程将被阻塞。只有当事件被设置为终止状态时,线程才会被唤醒。

异同点
虽然 AutoResetEvent 和 ManualResetEvent 都用于线程间的同步和通信,它们之间有以下几个关键的异同点:

重置行为:AutoResetEvent 在一个等待线程被唤醒后会自动将事件重置为非终止状态,而 ManualResetEvent 则需要显式地调用 Reset() 方法将事件重置为非终止状态。
信号通知:AutoResetEvent 只允许一个等待线程被唤醒,即使有多个线程等待;而 ManualResetEvent 允许多个等待线程被唤醒。
等待过程:AutoResetEvent 在一个等待线程被唤醒后,其他等待线程仍然会继续等待;而 ManualResetEvent 在一个等待线程被唤醒后,所有等待线程都会被唤醒。
使用场景和代码示例
根据上述的异同点,我们可以根据不同的需求来选择使用 AutoResetEvent 或 ManualResetEvent。

AutoResetEvent 使用示例
我们创建了两个工作线程,并使用 AutoResetEvent 来同步它们的执行。在主线程中,我们先唤醒第一个等待线程,然后等待一段时间再唤醒第二个等待线程。这样,每个线程只会被唤醒一次,然后自动重置事件,继续等待下一个信号。

  using System;
  using System.Threading;

  class Program
  {
      static AutoResetEvent autoResetEvent = new AutoResetEvent(false);

      static void Main(string[] args)
      {
          Thread thread1 = new Thread(Worker);
          Thread thread2 = new Thread(Worker);

          thread1.Start();
          thread2.Start();

          // 唤醒第一个等待线程
          autoResetEvent.Set();

          // 唤醒第二个等待线程
          Thread.Sleep(1000);
          autoResetEvent.Set();

          // 等待线程执行完毕
          thread1.Join();
          thread2.Join();
      }

      static void Worker()
      {
          Console.WriteLine("Worker started");
          autoResetEvent.WaitOne();
          Console.WriteLine("Worker finished");
      }
  }

ManualResetEvent 使用示例
我们同样创建了两个工作线程,但这次使用ManualResetEvent 来同步它们的执行。在主线程中,我们设置了事件为终止状态,这将唤醒所有等待线程。由于 ManualResetEvent 保持终止状态,每个线程只会被唤醒一次,然后继续执行直到结束。

  using System;
  using System.Threading;

  class Program
  {
      static ManualResetEvent manualResetEvent = newManualResetEvent(true);

      static void Main(string[] args)
      {
          Thread thread1 = new Thread(Worker);
          Thread thread2 = new Thread(Worker);

          thread1.Start();
          thread2.Start();

          // 唤醒所有等待线程
          manualResetEvent.Set();

          // 等待线程执行完毕
          thread1.Join();
          thread2.Join();
      }

      static void Worker()
      {
          Console.WriteLine("Worker started");
          manualResetEvent.WaitOne();
          Console.WriteLine("Worker finished");
      }
  }

阻塞多个线程并同时激活
如果需要阻塞多个线程并同时激活多个线程,建议使用 ManualResetEvent。原因是 ManualResetEvent 允许多个等待线程被唤醒,而 AutoResetEvent 只允许一个等待线程被唤醒。

下面是一个使用 ManualResetEvent 的示例代码:

using System;
using System.Threading;

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

    static void Main(string[] args)
    {
        Thread[] threads = new Thread[5];

        for (int i = 0; i < threads.Length; i++)
        {
            threads[i] = new Thread(Worker);
            threads[i].Start();
        }

        // 阻塞所有线程
        Console.WriteLine("Blocking all threads...");
        manualResetEvent.WaitOne();

        // 激活所有线程
        Console.WriteLine("Activating all threads...");
        manualResetEvent.Set();

        // 等待线程执行完毕
        foreach (Thread thread in threads)
        {
            thread.Join();
        }
    }

    static void Worker()
    {
        Console.WriteLine("Worker started");
        manualResetEvent.WaitOne();
        Console.WriteLine("Worker finished");
    }
}

在示例中创建了 5 个工作线程,并使用 ManualResetEvent 来阻塞和激活这些线程。执行的流程为:

主线程将 ManualResetEvent 设置为非终止状态,阻塞所有的工作线程;
主线程打印消息并将 ManualResetEvent 设置为终止状态,激活所有的工作线程;
等待所有线程执行完毕。文章来源地址https://www.toymoban.com/news/detail-828945.html

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

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

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

相关文章

  • Baumer工业相机堡盟工业相机如何使用BGAPISDK对两个万兆网相机进行触发同步(C#)

    Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩

    2024年02月09日
    浏览(49)
  • 12.3用信号量进行线程同步——生产者与消费者问题

    1.shell程序设计 2.内存管理 3.链接库 4.文件操作

    2024年02月04日
    浏览(41)
  • openCV 多线程调用多个海康威视摄像头(避免画面不同步),进行人脸识别

    1、创建多个线程来拉取不同的视频流,不使用多线程的话,所有的视频流就在排一个队,会出现画面不同步的情况 代码: 2、使用numpy将多个画面放在同一个frame中,图像就是矩阵,numpy是用来处理矩阵的类 代码:  进行人脸识别,网不好帧率太低

    2024年04月25日
    浏览(110)
  • .NET的CancellationTokenSource和ManualResetEvent结合使用

    一、CancellationTokenSource 是 C# 中的一个类,用于取消异步操作。它提供了一种机制,可以取消一个或多个异步操作。 CancellationTokenSource 包含以下主要方法: Cancel(): 该方法会取消所有挂起的操作,并引发 OperationCanceledException 异常。如果在调用 Cancel() 方法时没有挂起的操作,则

    2024年02月07日
    浏览(30)
  • 【Linux C | 多线程编程】线程同步 | 信号量(无名信号量) 及其使用例子

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 🤣本文内容🤣:🍭介绍 🍭 😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭 ⏰发布时间⏰: 本文未经允许,不得转发!!!

    2024年04月26日
    浏览(39)
  • C# 使用多线程,关闭窗体时,退出所有线程

    this.Close();   只是关闭当前窗口,若不是主窗体的话,是无法退出程序的,另外若有托管线程(非主线程),也无法干净地退出; Application.Exit();  强制所有消息中止,退出所有的窗体,但是若有托管线程(非主线程),也无法干净地退出; Application.ExitThread(); 强制中止调用

    2024年01月18日
    浏览(32)
  • 使用 Github 进行 Obsidian 笔记同步

    ​ 阅读需要 git 基础 在 Windows 中使用 安装 Obsidian Git(第三方插件) 和 git 配置环境 在安装好 obsidian git 后,进入其设置界面的最上方会提示当前 git 的配置情况,如果没有配置成功远程仓库 或者初始化 git ,会显示 “not already” 且没有 Automatic 选项,当配置成功后,会显示

    2024年02月04日
    浏览(50)
  • 实战演练 | 使用 Navicat 进行 MySQL 数据同步

    上一篇,我们介绍了 使用 Navicat 进行 MySQL 结构同步, 一般在数据库迁移、数据库升级、数据库维护情况下,往往会出现将数据库结构同步的需求。 数据同步也是数据库管理开发中最常规的操作之一,它是指将数据库中的数据在不同的数据库服务器之间进行同步,以确保数

    2024年04月26日
    浏览(35)
  • Linux 使用 PTP 进行时间同步

    PTP(精确时间协议)是一种用于在网络中进行时钟同步的协议。当与硬件支持结合使用时,PTP 能够达到亚微秒的精度,这种精度远高于 NTP 协议。 PTP 时间同步协议的支持分为内核空间和用户空间两部分。在 Linux 系统中,PTP 协议的实际实现称为 LinuxPTP,它是 PTPv2 根据 Linux 的

    2024年04月11日
    浏览(43)
  • C# 中多线程锁的使用经验

    C# 中多线程锁的使用经验:全局锁,实例锁         private static object _exeLock = new object();        static 静态的是全应用程序的资源。如果在一个类里定义了这样一个锁,你在调用使用这个类的时候,是NEW了一个对象,并把这个对象给了一个静态全局变量中保存。这时这个锁

    2024年03月14日
    浏览(55)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包