线程同步之ManualResetEvent类的用法

笔者的一台激光测厚设备的软件, 它有一个运动线程, 一个激光数据处理线程.

运动线程做的事就是由A点移动到B点, 然后再由B点移动回A点.

激光处理线程要做的事就是采集指定数量点的激光数据, 随着采集的点数增加, 耗时也会增加.

这两个线程就存在线程同步的问题, 预想的标准流程应该是这样的:

  • A点到B点运动开始一瞬间, 通知激光线程开始采集数据
  • 激光线程采集数据完成后, 通知运动线程继续, 这时运动线程决定当前是由A到B, 还是由B到A
  • 循环执行上述的动作.

这样的线程同步要求, 可以使用C#的一个封装windows内核信号量的类ManualResetEvent来实现, 它是笔者用得最多的一个类. 所以在这里重点记录下来.

ManualResetEvent的功能我们先做一个简要说明:

ManualResetEvent可以通知一个或多个正在等待的线程已发生事件,允许线程通过发信号互相通信,来控制线程是否可心访问资源

当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态。此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。

一旦它被终止,ManualResetEvent 将保持终止状态,直到它被手动重置。即对 WaitOne 的调用将立即返回。

可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。

看理论要结合代码验证, 这样更容易明白.

下面给出演示代码:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading;
 6
 7 namespace ManualResetEventState
 8 {
 9     class Program
10     {
11         static ManualResetEvent _mre = new ManualResetEvent(false);
12         static void Main(string[] args)
13         {
14             Console.WriteLine("输入1为Set()   开始运行");
15             Console.WriteLine("输入2为Reset() 暂停运行");
16             Thread[] _threads = new Thread[3];
17
18             for (int i = 0; i < _threads.Count(); i++)
19             {
20                 _threads[i] = new Thread(ThreadRun);
21                 _threads[i].Start();
22             }
23
24             while (true)
25             {
26                 switch (Console.ReadLine())
27                 {
28                     case "1":
29                         _mre.Set();
30                         Console.WriteLine("开始运行");
31                         break;
32                     case "2":
33                         _mre.Reset();
34                         Console.WriteLine("暂停运行");
35                         break;
36                     default:
37                         break;
38                 }
39             }
40         }
41
42         static void ThreadRun()
43         {
44             int _threadID = 0;
45             while (true)
46             {
47                 _mre.WaitOne();
48                 _threadID = Thread.CurrentThread.ManagedThreadId;
49                 Console.WriteLine("current Tread is " + _threadID);
50                 Thread.Sleep(TimeSpan.FromSeconds(2));
51
52             }
53         }
54     }
55 }

运行结果如下图:

本文源代码下载

时间: 2024-10-09 04:46:29

线程同步之ManualResetEvent类的用法的相关文章

C#多线程开发10:线程同步之Semaphore类

Semaphore类表示信号量. 信号量和互斥类似,只是信号量可以同时由多个线程使用,而互斥只能由一个线程使用.也就是说,使用信号量时,可以多个线程同时访问受保护的资源.下面实例演示了"学生到食堂就餐"的场景,一共有10个学生需要就餐,但是食堂每次只能接纳4名学生就餐,所以将信号量的计数设置为4,每次有4个任务(就餐任务)可以获得锁定.剩下的学生就必须等待,等到锁定被解除时,学生才可以继续获得锁定,进入食堂就餐. using System; using System.Threading

C#多线程开发8:线程同步之Mutex类

以下代码模拟"从自动取款机中取钱"的操作:当账户余额大于等于1000时,取出1000放入口袋.代码中使用两个线程同时执行取钱操作,若不进行同步处理,可能会存在两个线程同时进入取钱逻辑,导致最终取出2000的错误结果.所以代码中使用Mutex类同步线程访问取钱逻辑(临界资源). using System; using System.Threading; namespace MutexExample { class Program { private static Mutex mutex

ManualResetEvent 类的用法

引用:http://jingyan.baidu.com/article/0eb457e50949d203f1a9050f.html 先说是一下  ManualResetEvent 是一线程用来控制别一个线程的信号.大家可以把它看成 操作系统原理中说到的pv操作如下图所说是 ManualResetEvent 对象起一个信使的作用. ManualResetEvent 对象的两个控制方法. 1.this.manualEvent.Reset(); //将事件状态设置为非终止状态,导致线程阻止. 2.th

JUC——线程同步辅助工具类(Semaphore,CountDownLatch,CyclicBarrier)

CountDownLatch CountDownLatch是一个计数器闭锁,通过它可以完成类似于阻塞当前线程的功能,即:一个线程或多个线程一直等待,直到其他线程执行的操作完成.CountDownLatch用一个给定的计数器来初始化,该计数器的操作是原子操作,即同时只能有一个线程去操作该计数器.调用该类await方法的线程会一直处于阻塞状态,直到其他线程调用countDown方法使当前计数器的值变为零,每次调用countDown计数器的值减1.当计数器值减至零时,所有因调用await()方法而处于

多线程下的进程同步(线程同步问题总结篇)

之前写过两篇关于线程同步问题的文章(一,二),这篇中将对相关话题进行总结,本文中也对.NET 4.0中新增的一些同步机制进行了介绍. 首先需要说明的是为什么需要线程功能同步.MSDN中有这样一段话很好的解释了这个问题: 当多个线程可以调用单个对象的属性和方法时,对这些调用进行同步处理是非常重要的.否则,一个线程可能会中断另一个线程正在执行的任务,使该对象处于一种无效状态. 也就说在默认无同步的情况下,任何线程都可以随时访问任何方法或字段,但一次只能有一个线程访问这些对象.另外,MSDN中也给出定

JAVA学习笔记之多线程专题(一):线程同步安全处理

关于多线程操作,我相信大家都不陌生,如何开启一个线程之类我想就不用太详细的去描述,今天我们就来讲讲线程同步的安全的问题. 对于线程同步安全问题,一般是一个多线程对同一个资源同时操作的时候,会出现资源同时操作造成线程不安全的问题.那么这个时候我们需要去对公共资源进行同步保护.这个时候有三种情况 1.同步代码块,这个同步的锁是任意一个对象: 2.方法同步,这个同步的锁就是该方法所在的类: 3.静态方法同步,这个同步的锁是该方法所在类的字节码. 接下来,我们举一个例子来说明多线程对同一个资源进行操作的

【WIN32进阶之路】:线程同步技术纲要

前面博客讲了互斥量(MUTEX)和关键段(CRITICAL SECTION)的使用,想来总觉不妥,就如盲人摸象一般,窥其一脚而言象,难免以偏概全,追加一篇博客查遗补漏. win32下的线程同步技术分为用户模式下的线程同步和用内核对象进行线程同步两大类. 用户模式下的线程同步和用内核对象进行线程同步有以下的明显差异: 1.用户模式下的线程同步不需要进入操作系统核心,直接在用户模式就可以进行操作. 2.用内核对象进行线程同步需要进入操作系统核心,用户模式切换至核心模式大约花费1000个CPU周期.

.NET多线程编程(3)——线程同步

随着对多线程学习的深入,你可能觉得需要了解一些有关线程共享资源的问题. .NET framework提供了很多的类和数据类型来控制对共享资源的访问. 考虑一种我们经常遇到的情况:有一些全局变量和共享的类变量,我们需要从不同的线程来更新它们,可以通过使用System.Threading.Interlocked类完成这样的任务,它提供了原子的,非模块化的整数更新操作. 还有你可以使用System.Threading.Monitor类锁定对象的方法的一段代码,使其暂时不能被别的线程访问. System

C#中的几个线程同步对象方法

在编写多线程程序时无可避免会遇到线程的同步问题.什么是线程的同步呢? 举个例子:如果在一个公司里面有一个变量记录某人T的工资count=100,有两个主管A和B(即工作线程)在早一些时候拿了这个变量的值回去 ,过了一段时间A主管将T的工资加了5块,并存回count变量,而B主管将T的工资减去3块,并存回count变量.好了,本来T君可以得到102块的工资的,现在就变成98块了.这就是线程同步要解决的问题. 在.Net的某些对象里面,在读取里面的数据的同时还可以修改数据,这类的对象就是“线程安全”