线程与异步在监控系统中的应用

        监控系统应用比较广泛,监控对象也是包罗万象,以下就拿监控注塑机器来说,机器的主要参数如开模、合模、熔胶、射胶、冷却、松退、顶出等运行参数需要实时监控,监控的机器不止一台,是很多台,监控到的数据了要提交到存储系统保存起来;

1、如何监控机器的在线与离线状态

   实现方法:创建一个后台线程,线程内一个while循环,循环内异步PingPing完成事件内确定机器的在线状态;

//创建ping线程
            _pingThread = new Thread(PingMachines, 1024 * 30);
            _pingThread.IsBackground = true;
        _pingThread.Start();

 		/// <summary>
        /// ping所有的机器 变量_PingThreadStop在关闭程序时为True
        /// </summary>
        private void PingMachines()
        {
            string machinename, ip,tmpstr;
            try
            {
                while (!_PingThreadStop)
                {
                    if (_PingCount > 0) { continue; }
                    lock (olock) ;
 //机器列表
                    foreach (DataRow dr in opcdata.tbMachines.Rows)
                    {
  //获取要ping的机器及IP
                        machinename = dr["MachineName"].ToString();
                        ip = dr["MachineIP"].ToString();
                        dr["MachineOnline"] = _OnlineMachine.TryGetValue(machinename, out tmpstr);
  						//ping计数器,避免产生太多ping
                        Interlocked.Increment(ref _PingCount);
//ping方法
                        toolhelper.PingIP(machinename, ip,PingCompletedEvent);                        
                        Thread.Sleep(1000);
                    }
                    Thread.Sleep(2000);
                }
            }
            catch (Exception ex)
            {
                log4.Error("error", ex);
            }
        }
/// <summary>
        /// ping 完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void PingCompletedEvent(object sender, PingCompletedEventArgs e)
        {
            string machinename = "";
            string ip = "";
            string tmpstr = "";
            bool findflag;
            try
            {
                //ping计数器减1
                Interlocked.Decrement(ref _PingCount);
                //获取ping用户自定义数据
                if (e.UserState is pingSendData)
                {
                    machinename = ((pingSendData)e.UserState).machineNo;
                    ip = ((pingSendData)e.UserState).clientIP;
                }
                //ping 结果
                bool pingRes = e.Reply.Status == IPStatus.Success;
                //获取在线机器
                findflag = _OnlineMachine.TryGetValue(machinename, out tmpstr);
                //离线切换到在线
                if (pingRes && !findflag)
                {
                    _OnlineMachine.TryAdd(machinename, machinename);
                    OPCObj.AddMachineAlarm(machinename);
                }
                else
                {
                    //在线切换到离线
                    if (!pingRes && findflag)
                    {
                        _OnlineMachine.TryRemove(machinename, out tmpstr);
                    }
                }
                
            }
            catch (Exception ex)
            {
                log4.Error("error", ex);
            }
            finally {
                //释放ping对象
                if (sender is Ping)
                {
                    (sender as Ping).Dispose();
                }
            }
        }


        /// <summary>
        /// 判断IP是否通
        /// </summary>
        /// <param name="machineNo"></param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public  void PingIP(string machineNo,string ip, PingCompletedEventHandler PingCompletedEvent)
        {
            Ping ping = new Ping();
            ping.PingCompleted += PingCompletedEvent;
            ping.SendAsync(ip,2000, new pingSendData { machineNo = machineNo, clientIP = ip });
        }

2、如何将获取到数据异步提交到API接口

   实现方法:创建post对象,准备好post数据,异步上传数据,上传完成事件处理结果;

/// <summary>
        /// 数据提交主方法
        /// </summary>
        /// <returns></returns>
        public  void  SubmitData(string Machine, int ProductQT,string Createtime, out bool success, out string errmsg, UploadDataCompletedEventHandler UploadDataCompletedEvent)
        {
            success = true;
            errmsg = ""; 
DataRow[] drs;
            OPCTool opctool = new OPCTool();
            //重新获取当前最新参数数据
            drs = RunDataTable.Select(自已的查询条件));
            if (drs == null || drs.Length == 0) { success = false; return; }
            WebException webexec;
            try
            {
                using (DataTable tmpTable1 = drs.CopyToDataTable()) {
                                     
                        Dictionary<string, object> inputs = new Dictionary<string, object>();
                        inputs.Add("machine", Machine);
                        inputs.Add("ip", MachineIPDict.ContainsKey(Machine));
                        inputs.Add("paraslist", tmpTable1);
                        inputs.Add("currtime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        inputs.Add("modeluenum", ProductQT);
                        inputs.Add("url", API_Url);
 //自定义数据
                        Dictionary<string, string> userToken = new Dictionary<string, string>();
                        userToken.Add("title", "RUNDATA");
                        userToken.Add("url", API_Url);
                        userToken.Add("machine", inputs["machine"].ToString());
                        opctool.HttpPost(inputs["url"].ToString(), JsonConvert.SerializeObject(inputs), UploadDataCompletedEvent,out webexec, "", userToken);
                        if (webexec != null) {
                            success = false;
                            errmsg = webexec.StackTrace;
                        }
                        inputs = null;
                    }
             }
            finally
            {
                opctool = null;
                drs = null;
            }
        }

         /// <summary>
        /// 异步POST
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData">上传数据</param>
        /// <param name="UploadDataCompleted">上传完成事件</param>
        /// <param name="ContentType"></param>
        /// <param name="ex">调用异常</param>
        /// <param name="userToken">用户自定义数据</param>
        public void HttpPost(string url, string postData, UploadDataCompletedEventHandler UploadDataCompleted, out WebException ex,string ContentType = "application/json",object userToken=null) {
            using (var client = new WebClient())
            {
                client.UploadDataCompleted += UploadDataCompleted;
                try
                {
                    client.Headers.Add("Content-Type", ContentType==""? "application/json": ContentType);
                    byte[] poststream = Encoding.UTF8.GetBytes(postData);
                    client.UploadDataAsync(new Uri(url),"POST", poststream,userToken);
                    ex = null;
                }
                catch (WebException exce)
                {
                    ex = exce;
                }
            }
        }

        /// <summary>
        /// 上传数据完成事件处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void UploadDataCompletedEvent(object sender, UploadDataCompletedEventArgs e)
        {
            StringBuilder sb = new StringBuilder();
            Dictionary<string, string> userToken = new Dictionary<string, string>();
            if (e.Error == null)
            {
//获取api返回数据
                string resultstr = Encoding.UTF8.GetString(e.Result);
                //转换为json对象
                JObject result = (JObject)JsonConvert.DeserializeObject(resultstr);
               
                if (e.UserState != null && (e.UserState is Dictionary<string, string>)) {
                    userToken = (e.UserState as Dictionary<string, string>);
                }
                if (!(bool)result["success"])
                {
                    outputmsg(result["resmsg"].ToString());
                }
                else
                {
                    if (userToken.ContainsKey("title")) {
                        sb.Append(userToken["title"]);
                    }
                    if (userToken.ContainsKey("machine"))
                    {
                        sb.Append(" 机器:"+userToken["machine"]);
                    }
                    if (userToken.ContainsKey("url"))
                    {
                        sb.Append(" 提交网址:" + userToken["url"]);
                    }
                    outputmsg(sb.ToString() + "成功 ");
                    sb = null;
                    userToken = null;
                }
            }
            else {
                if (userToken.ContainsKey("title"))
                {
                    sb.Append(userToken["title"]);
                }
                if (userToken.ContainsKey("machine"))
                {
                    sb.Append(" 机器:" + userToken["machine"]);
                }
                if (userToken.ContainsKey("url"))
                {
                    sb.Append(" 提交网址:" + userToken["url"]);
                }
                sb.Append(" 失败,错误:"+e.Error.StackTrace);
                outputmsg(sb.ToString());
                sb = null;
                userToken = null;
            }
        }

    异步的好处就是动作不会对线程造成阻塞,不会造成CPU利率居高不下,如果一开始用的是同步,改为异步后,CPU利用率会马上降下来并保持小范围的波动;




猜你喜欢

转载自blog.csdn.net/baronyang/article/details/75116180