• C# ManualResetEvent 类分析


    C# ManualResetEvent 类分析

    官方解释

    链接: 微软官方文档

    1. 需求

    你可能有这样一种需求:有一个重复的或者耗时长的工作线程,界面有一个暂停按钮,当你按下的时候,期望工作线程能暂停一下.当你在界面按下继续按钮的时候,期望工作线程能从刚刚停下的那一刻重新开始工作.

    1.1 创造一个虚拟的需求

    我希望有一个界面,后台重复每秒刷新时间,一个暂停按钮,一个继续按钮.
    在这里插入图片描述

    1.2 V1.0 版本

    用一个静态变量去控制更新时间的线程,当点击暂停时,时间停止更新,点击继续时,时间继续跳动.开启了一个线程,将更新时间的函数放置在一个while循环里,可以打开任务管理器看到,CPU占用率直接干到10%以上.无论是点击暂停还是继续按钮,实际上这个线程CPU一直在开销,于是我们有了一个新需求...
    在这里插入图片描述

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace ManualResetEvent
    {
        public partial class Form1 : Form
        {
            private static bool Pause = false;
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                Task.Run(() =>
                {
                    while(true)
                    {
                        if(Pause)
                        {
                            continue;
                        }
                        label1.Invoke(new Action(() =>
                        {
                            var time = DateTime.Now;
                            label1.Text = time.ToString("yyyy年MM月dd日 HH:mm:ss");
                        }));
                    }
                });
            }
    
            private void btn_Pause_Click(object sender, EventArgs e)
            {
                Pause = true;
            }
    
            private void btn_Continue_Click(object sender, EventArgs e)
            {
                Pause = false;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    1.3 V1.1 版本

    被暂停时, 线程处于休眠状态, 不占用CPU,让CPU休息一下.
    于是用ManualResetEvent替代V1.0版本简单的布尔量.
    可以看到,当正常更新时间,CPU占用跟以前一样,但是当按下暂停键的时候,CPU占用率几乎为0!
    未暂停状态
    暂停状态

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace ManualResetEvent
    {
        public partial class Form1 : Form
        {
            //private static bool Pause = false;
            private static System.Threading.ManualResetEvent m_WaitHandle = new System.Threading.ManualResetEvent(true);
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                Task.Run(() =>
                {
                    while(true)
                    {
                        //if (Pause)
                        //{
                        //    continue;
                        //}
                        m_WaitHandle.WaitOne();
                        label1.Invoke(new Action(() =>
                        {
                            var time = DateTime.Now;
                            label1.Text = time.ToString("yyyy年MM月dd日 HH:mm:ss");
                        }));
                    }
                });
            }
            //暂停
            private void btn_Pause_Click(object sender, EventArgs e)
            {
                //Pause = true;
                m_WaitHandle.Reset();
            }
            //继续
            private void btn_Continue_Click(object sender, EventArgs e)
            {
                //Pause = false;
                m_WaitHandle.Set();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    2. 分析

    2.1 WaitOne阻止当前线程

    当程序执行到WaitOne方法时,将判断ManualResetEvent是否有信号,有信号时不阻塞,没信号时阻塞,WaitOne后面的语句将暂停执行.

    2.2 Set设置信号, 亮绿灯

    Set方法将通知其他线程的WaitOne,继续执行后面的语句.

    2.3 Reset重置信号, 亮红灯

    Reset方法将使其他线程的WaitOne阻塞.

  • 相关阅读:
    软件测试概念集锦
    PX4飞行测试
    函数式编程-Stream流(三更草堂)
    面试官:项目中最大的风险是什么?
    6 从物理层到MAC层
    适合学生的蓝牙耳机哪款平价?学生平价蓝牙耳机推荐
    一文读懂 BizDevOps:数字化转型下的技术破局
    设计模式-学习笔记
    【Python】将Python中的多维列表进行展开
    Hive调优及优化(包含数据倾斜和小文件问题)
  • 原文地址:https://blog.csdn.net/weixin_42117950/article/details/125407944