学习|C#线程中AutoResetEvent的使用

时间:2022-07-23
本文章向大家介绍学习|C#线程中AutoResetEvent的使用,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为3106,预计阅读8分钟

前言

前一篇《学习|C#的EventHandler的委托使用》介绍了EventHandler的简单使用,本篇主要介绍线程中的AutoResetEvent来实现整个读卡器的操作过程。

视频场景

读卡器操作

微卡智享

与读卡器的对接也是调用的读卡器厂家的动态库,根据读卡器厂家的设备操作流程:

其实从上面的读卡器操作流程来看,也能看出来为什么我们上一篇文章要讲EventHandler了,这样就可以把读卡的逻辑和读到卡数据后的业务逻辑进行分开了。话不多说,正篇开始。

AutoResetEvent简介

微卡智享

AutoResetEvent对象用来进行线程同步操作,AutoResetEvent类继承waitHandle类。waitOne()方法就继承来自waitHandle类。

AutoResetEvent的主要方法

#

主要方法

1

AutoResetEvent(bool initialState):构造函数,参数false:无信号,子线程的WaitOne方法不会被自动调用 true:有信号,子线程的WaitOne方法会被自动调用

2

Reset ():将事件状态设置为非终止状态,导致线程阻止;如果该操作成功,则返回true;否则,返回false。

3

Set ():将事件状态设置为终止状态,允许一个或多个等待线程继续;如果该操作成功,则返回true;否则,返回false。

4

WaitOne():阻止当前线程,直到收到信号。

5

WaitOne(TimeSpan, Boolean) :阻止当前线程,直到当前实例收到信号,使用 TimeSpan 度量时间间隔并指定是否在等待之前退出同步域。

上面就是AutoResetEvent的主要方法,从上面的主要方法中我们可以看到,实现读卡器每100耗秒进行检测,原来通过线程是sleep进行处理,现在可以使用WaitOne的方式,并且通过这个方法,我们可以在外部实现读卡器重连的调用。

本项目场景

本项目(开头视频)中因为读卡器使用的网络通讯,所以我们要考虑出现异常情况下实现读卡器自动重连。

  • 如果存在网络中断的时候我们要考虑到自动重连。
  • 在车牌识别时发现是会员,但是没有读到卡信息,有可能读卡器出现异常,也要进行自动重连。

根据上面的情况,我们就可考虑除了读卡数据异常时需要自动重新连接,还要在外部接口中封装一个函数,可以从外部直接调用重连读卡器。实际项目中对读卡器的操作没法贴上来,这里我们就接着一个DEMO,模拟一下这个场景。

代码演示

微卡智享

接着我们的threaddemo,在CTest的类中我们开始改造。

先定义一个AutoResetEvent,和等待的毫秒waitTime。

然后定义一个Reset的方法,模拟读卡器重启。

原来的停止方法中加入isRunning的开关,再调用exitEvent的Reset和Set,这样就可以区分是重启还是终止。

我们在循环的操作里面加入一个随机数生成,取值为0到13内

  • 如果取值的数字小于10,那就正常发送数据。
  • 如果取值的数字等于10,那就直接抛出异常,然后在异常中内部模拟Reset重连读卡器。
  • 如果取值的数字大于10,也直接进行重连,只不过不用抛出异常。

代码

using System;using System.Collections.Generic;using System.Drawing.Text;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;
namespace threaddemo{    public class CTest : Inftest,IDisposable    {        public int id;
        private AutoResetEvent exitEvent;
        private Thread thread;
        private int waitTime = 100;
        private bool disposed = false;
        private bool IsRunning;
        public int cs = 0;        public CTest(int _id)        {            id = _id;            exitEvent = new AutoResetEvent(false);            thread = new Thread(ReadThreadRun);            thread.IsBackground = true;        }

        public event EventHandler<testEvent> DataReceived;
        public void Dispose()        {           // Dispose(true);            GC.SuppressFinalize(this);        }
        protected virtual void Dispose(bool disposing)        {            if (!this.disposed)            {                if (disposing)                {                    try                    {                        Stop();
                    }                    catch (Exception)                    {
                    }                }                disposed = true;            }        }
        public void Start()        {            IsRunning = true;            thread.Start();        }
        public void Stop()        {            IsRunning = false;            exitEvent.Reset();            exitEvent.Set();            RaiseDataReceived("手动停止");        }

        public void Reset()        {            exitEvent.Reset();            exitEvent.Set();        }
        public void setcs(int _cs)        {            cs = _cs;
        }

        private void RaiseDataReceived(string msg)        {            DataReceived?.Invoke(this, new testEvent(msg, id));        }
        /// <summary>        /// 接收线程        /// </summary>        private void ReadThreadRun()        {            while (IsRunning)            {                try                {                    if (exitEvent.WaitOne(waitTime))                    {                        if (IsRunning) {                            Thread.Sleep(1000);                            id++;                            if (id % 5 == 0)                            {                                throw new Exception("余数:0");                            }else if (id % 5 == 1)                            {                                try                                {                                    throw new Exception("故意出错");                                }                                catch(Exception ex)                                {                                    RaiseDataReceived(ex.Message);                                    Reset();                                }                            }                            RaiseDataReceived("状态:重启");                        }                        else                        {                            Thread.Sleep(1000);                            RaiseDataReceived("停止");                        }                    }
                    Random rd = new Random();                    int count = rd.Next(0, 13);                    if (count < 10)                    {                        RaiseDataReceived(count.ToString());                       }                    else if (count == 10)                    {                        throw new Exception("throw 数字:" + count);                    }                    else                    {                        RaiseDataReceived("数字:" + count + " Reset");                        Reset();                    }                }                catch (Exception ex)                {                    RaiseDataReceived("error " + ex.Message);                    Reset();                }
                //Thread.Sleep(100);            }        }    }}

实现效果

源码地址

https://github.com/Vaccae/EventHandlerDemo.git