栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

C# ManualResetEvent 类分析

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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.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();
        }
    }
}

2. 分析 2.1 WaitOne阻止当前线程

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

2.2 Set设置信号, 亮绿灯

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

2.3 Reset重置信号, 亮红灯

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1023928.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号