c#后台線程更新界面


參考文章《C# 線程更新UI界面

 

主窗口

        public frmMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 主窗口加載事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_Load(object sender, EventArgs e)
        {
            try
            {

                //設置默認狀態
                mc_MachineStatusHander = new Common.MachineStatusHandler();                
                mc_MachineStatusHander.mc_MachineProduceStatusHandler.UpdateMachineSignalDelegate += UpdateMachineSignalStatus;//后台線程中指定委托為更新界面方法

                mc_MachineStatusHander.ChangeStatus("Online", "運行", "WesChen", "001A");
                SettingLight();

            }
            catch (Exception ex)
            {
                ShowErrorMessage(ex.Message, "系統初始化");
                this.Close();
            }
        }

 

界面更新主方法

        /// <summary>
        /// 獲取機器信號,並更新界面
        /// </summary>
        /// <param name="singnal">機器信號</param>
        delegate void UpdateMachineProduceSignalDelegate(Common.MachineProduceStatusHandler.SignalType singnal);
        private void UpdateMachineSignalStatus(Common.MachineProduceStatusHandler.SignalType signal)
        {
            if (InvokeRequired)
            {
                this.Invoke(new UpdateMachineProduceSignalDelegate(delegate (Common.MachineProduceStatusHandler.SignalType s)
                {

                    if (signal.ToString().IndexOf("X01") != -1)
                    {
                        btn_SignalX01.BackColor= System.Drawing.Color.FromArgb(255, 255, 255);
                        btn_SignalX01.ForeColor = System.Drawing.Color.FromArgb(0, 0, 0);
                    }
                    else
                    {
                        btn_SignalX01.BackColor = System.Drawing.Color.FromArgb(38, 45, 58);
                        btn_SignalX01.ForeColor = System.Drawing.Color.FromArgb(255, 255, 255);
                    }                    

                    lab_ProductCount.Text = "累計生產數量:" + mc_MachineStatusHander.mc_MachineProduceStatusHandler.ProductCount;
                    lab_LastLifeCycleTime.Text = "最后一次生產用時:" + Common.CommonFunction.FormatMilliseconds(mc_MachineStatusHander.mc_MachineProduceStatusHandler.LastProductUseMilliseconds);

                }), signal);
            }
            else
            {
                if (signal.ToString().IndexOf("X01") != -1)
                {
                    btn_SignalX01.BackColor = System.Drawing.Color.FromArgb(255, 255, 255);
                    btn_SignalX01.ForeColor = System.Drawing.Color.FromArgb(0, 0, 0);
                }
                else
                {
                    btn_SignalX01.BackColor = System.Drawing.Color.FromArgb(38, 45, 58);
                    btn_SignalX01.ForeColor = System.Drawing.Color.FromArgb(255, 255, 255);
                }               

                lab_ProductCount.Text = "累計生產數量:" + mc_MachineStatusHander.mc_MachineProduceStatusHandler.ProductCount;
                lab_LastLifeCycleTime.Text = "最后一次生產用時:" + Common.CommonFunction.FormatMilliseconds(mc_MachineStatusHander.mc_MachineProduceStatusHandler.LastProductUseMilliseconds);

            }
        }

后台線程

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Text.RegularExpressions;
using System.Diagnostics;

namespace MES_MonitoringClient.Common
{
    /// <summary>
    /// 機器生產狀態
    /// </summary>
    public class MachineProduceStatusHandler
    {

        /// <summary>
        /// 信號類型
        /// </summary>
        public enum SignalType
        {
            Unknow,

            X01,
            X02,
            X03,

            X01_X02,
            X01_X03,

            X02_X03,

            X01_X02_X03
        }

        /// <summary>
        /// 回復信號前綴
        /// </summary>
        private static string singnalDefaultStart = Common.ConfigFileHandler.GetAppConfig("GetSerialPortDataDefaultSignal_StartPrefix");
        /// <summary>
        /// 回復信號后綴
        /// </summary>
        private static string singnalDefaultEnd = Common.ConfigFileHandler.GetAppConfig("GetSerialPortDataDefaultSignal_EndPrefix");

        /*-------------------------------------------------------------------------------------*/


        /// <summary>
        /// 產品生命周期(計算時間)
        /// </summary>
        //private List<MachineProcedure> _MachineProcedureListForTime=null;

        /// <summary>
        /// 產品生命周期(計算次數)
        /// </summary>
        private List<MachineProcedure> _MachineProcedureListForCount=null;


        /// <summary>
        /// 產品周期計數(生產數量)
        /// </summary>
        public int ProductCount = 0;

        /// <summary>
        /// 空產品周期計數(不完整[空啤]生產數量)
        /// </summary>
        public int ProductErrorCount = 0;

        /// <summary>
        /// 單次產品周期秒數
        /// </summary>
        public long LastProductUseMilliseconds = 0;

        /// <summary>
        /// 
        /// </summary>
        public Nullable<DateTime> LastX03SignalGetTime = null;

        /// <summary>
        /// 上一個信號
        /// </summary>
        public SignalType LastSignal;


        /// <summary>
        /// 更新機器信號后更新界面的方法與委托
        /// </summary>
        /// <param name="signalType"></param>
        public delegate void UpdateMachineSignal(SignalType signalType);
        public UpdateMachineSignal UpdateMachineSignalDelegate;

        /*-------------------------------------------------------------------------------------*/

        /// <summary>
        /// 構造函數,處理初始化的參數
        /// </summary>
        public MachineProduceStatusHandler()
        {
            //產品生命周期(計算時間)
            //_MachineProcedureListForTime = new List<MachineProcedure>();

            //產品生命周期(計算次數)
            _MachineProcedureListForCount = new List<MachineProcedure>();
        }


        /*-------------------------------------------------------------------------------------*/

        /// <summary>
        /// 更新信號方法
        /// </summary>
        /// <param name="newSingnal">新信號</param>
        public void ChangeSignal(string newSingnal)
        {
            string convertSingnalString = ConvertSingnalString(newSingnal);

            //判斷是正常的信號
            if (!string.IsNullOrEmpty(convertSingnalString))
            {
                //判斷X信號
                SignalType convertSingnalStatusType = ConvertSingnalStatus(convertSingnalString);

                if (convertSingnalStatusType != LastSignal)
                {
                    

                    #region 與上一次信號不同

                    if (convertSingnalStatusType == SignalType.X03)
                    {
                        #region 自動信號(區分上一個信號)


                        _MachineProcedureListForCount.Add(new MachineProcedure()
                        {
                            ProcedureID = convertSingnalString,
                            ProcedureCode = convertSingnalStatusType.ToString(),
                            ProcedureName = "自動",
                        });


                        if (LastSignal == SignalType.X01_X03)
                        {
                            //結束產品周期並計時
                            if (LastX03SignalGetTime.HasValue)
                            {
                                LastProductUseMilliseconds = (System.DateTime.Now - LastX03SignalGetTime.Value).Milliseconds;
                            }
                            LastX03SignalGetTime = System.DateTime.Now;
                        }
                        else if (LastSignal == SignalType.X02_X03)
                        {
                            //必須包含完整的生命周期才計數
                            if (CheckHaveRealProduceProcess(_MachineProcedureListForCount))
                            {
                                //計數
                                ProductCount++;

                                _MachineProcedureListForCount.Clear();
                                _MachineProcedureListForCount.Add(new MachineProcedure()
                                {
                                    ProcedureID = convertSingnalString,
                                    ProcedureCode = convertSingnalStatusType.ToString(),
                                    ProcedureName = "自動",
                                });
                            }
                        }

                        #endregion
                    }
                    else if (convertSingnalStatusType == SignalType.X01_X03 || convertSingnalStatusType == SignalType.X02_X03)
                    {
                        #region 開模完成==射膠完成(不區分上一個信號)
                        //產品生命周期(計算數量)
                        if (_MachineProcedureListForCount != null && _MachineProcedureListForCount.Count > 0)
                        {
                            //信號
                            string procedureNameString = string.Empty;
                            if (convertSingnalStatusType == SignalType.X01_X03) procedureNameString = "開模完成";
                            else if (convertSingnalStatusType == SignalType.X02_X03) procedureNameString = "自動射膠";

                            _MachineProcedureListForCount.Add(new MachineProcedure()
                            {
                                ProcedureID = convertSingnalString,
                                ProcedureCode = convertSingnalStatusType.ToString(),
                                ProcedureName = procedureNameString,
                            });
                        }

                        #endregion
                    }

                    #endregion

                    //上一個信號
                    LastSignal = convertSingnalStatusType;

                    //根據信號更新界面
 UpdateMachineSignalDelegate(LastSignal);
                }
            }
        }

        /// <summary>
        /// 匹配信號是否正常
        /// 並返回信號中的模式數字
        /// </summary>
        /// <param name="inputSingnal">原信號</param>
        /// <returns></returns>
        private string ConvertSingnalString(string inputSingnal)
        {
            Regex regex = new Regex("^" + singnalDefaultStart + "[a-fA-F0-9]{4}" + singnalDefaultEnd + "$");
            Match match = regex.Match(inputSingnal);

            if (match.Success)
            {
                Regex regexMiddle = new Regex("(?<=(" + singnalDefaultStart + "))[.\\s\\S]*?(?=(" + singnalDefaultEnd + "))", RegexOptions.Multiline | RegexOptions.Singleline);
                Match matchMiddle = regexMiddle.Match(inputSingnal);

                return matchMiddle.Value;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 模式數字轉換為X[]信號
        /// </summary>
        /// <param name="inputSingnal">模式數字[0800,0400,0200,0C00,0A00,0600,0E00等模式數字]</param>
        /// <returns></returns>
        private SignalType ConvertSingnalStatus(string inputSingnal)
        {
            if (inputSingnal == "0800") return SignalType.X01; //開模終止信號
            else if (inputSingnal == "0400") return SignalType.X02;//射膠信號
            else if (inputSingnal == "0200") return SignalType.X03;//自動運行模式信號

            else if (inputSingnal == "0C00") return SignalType.X01_X02;
            else if (inputSingnal == "0A00") return SignalType.X01_X03;
            else if (inputSingnal == "0600") return SignalType.X02_X03;

            else if (inputSingnal == "0E00") return SignalType.X01_X02_X03;

            else return SignalType.Unknow;
        }

        /// <summary>
        /// 判斷是否是真實的生產流程
        /// </summary>
        /// <param name="oldMachineProcedureList"></param>
        /// <returns></returns>
        private bool CheckHaveRealProduceProcess(List<MachineProcedure> oldMachineProcedureList)
        {
            bool resultFlag = false;

            bool isX01_X03 = false;
            bool isX02_X03 = false;
            bool isX03 = false;

            //判斷是否有完整的信號
            foreach (var processItem in oldMachineProcedureList)
            {
                if (processItem.ProcedureCode == SignalType.X01_X03.ToString()) isX01_X03 = true;
                if (processItem.ProcedureCode == SignalType.X02_X03.ToString()) isX02_X03 = true;
                if (processItem.ProcedureCode == SignalType.X03.ToString()) isX03 = true;
            }

            //完整的信號則算正常生產流程
            if (isX01_X03 && isX02_X03 && isX03) resultFlag = true;

            return resultFlag;
        }
    }
}

 

 以上方法是可以正常從類內部更新winform界面的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM