C#--Modbus-一主多从-委托跨线程更新UI界面

2021/4/17 20:25:27

本文主要是介绍C#--Modbus-一主多从-委托跨线程更新UI界面,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

以下是学习笔记

一,接线图

  3台仪表设备接在一起

 

 二,界面设计:

 

 

三,代码实现:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using DAL;

namespace ModbusDemo
{
    //委托跨线程更新UI步骤【1】:声明一个delegate委托类型:UpdateDelegate。
    delegate void UpdateDelegate();
    public partial class FrmMain : Form
    {
        public FrmMain()
        {
            InitializeComponent();
            this.Load += FrmMain_Load;
        }
        //委托跨线程更新UI步骤【2】:创建一个UpdateDelegate类型的对象。
        UpdateDelegate updateGUI;

        Modbus objMod = new Modbus();
        bool CommOK = false;
        bool ReadEnable = true;
        Dictionary<int, byte[]> CommValue = new Dictionary<int, byte[]>();
        Dictionary<int, List<string>> CurrentValue = new Dictionary<int, List<string>>();

        private void FrmMain_Load(object sender, EventArgs e)
        {
            //委托跨线程更新UI步骤【3】:给updateGUI(委托)对象绑定一个方法。
            updateGUI = UpdateUI;

            for (int i = 0; i < 5; i++)
            {
                this.cmb_1stNum.Items.Add(i.ToString());
                this.cmb_2ndNum.Items.Add(i.ToString());
                this.cmb_3rdNum.Items.Add(i.ToString());
            }


            if (objMod.OpenMyComm(9600, "COM3", 8, System.IO.Ports.Parity.None, System.IO.Ports.StopBits.One))
            {
                CommOK = true;
            }
            else
            {
                MessageBox.Show("串口打开失败,请检查串口!", "串口打开 ");
                return;
            }

            Thread t = new Thread(new ThreadStart(Comm));
            t.IsBackground = true;
            t.Start();
        }

        /// <summary>
        /// 线程执行的方法
        /// </summary>
        private void Comm()
        {
            while (CommOK)
            {
                //第一步:数据读取
                //对于从站1,读取0-4共5个寄存器
                CommValue[1] = objMod.ReadKeepReg(1, 0, 5);
                //对于从站2和从站3,读取0-3共4个寄存器
                CommValue[2] = objMod.ReadKeepReg(2, 0, 4);
                CommValue[3] = objMod.ReadKeepReg(3, 0, 4);

                //第二步:数据解析
                AnalyseData();

                //第三步:更新到界面
                //委托跨线程更新UI步骤【6】:在线程中调用委托。
                updateGUI();
            }
        }

        /// <summary>
        /// 数据解析
        /// </summary>
        private void AnalyseData()
        {
            byte[] res;
            List<string> list;
            foreach (int item in CommValue.Keys)
            {
                switch (item)
                {
                    //从站1
                    case 1:
                        res = CommValue[1];
                        list = new List<string>();
                        if (res != null && res.Length == 10)
                        {
                            //计数值
                            Int32 res1 = ByteArrayToInt32(new byte[4] { res[0], res[1], res[2], res[3] });
                            list.Add(res1.ToString());
                            Int16 res2 = ByteArrayToInt16(new byte[2] { res[6], res[7] });
                            list.Add(res2.ToString());
                        }
                        CurrentValue[1] = list;
                        break;
                    case 2:
                        res = CommValue[2];
                        list = new List<string>();
                        if (res != null && res.Length == 8)
                        {
                            //计时值
                            Int32 res1 = ByteArrayToInt32(new byte[4] { res[0], res[1], res[2], res[3] });
                            list.Add(res1.ToString());
                            Int16 res2 = ByteArrayToInt16(new byte[2] { res[6], res[7] });
                            list.Add(res2.ToString());
                        }
                        CurrentValue[2] = list;
                        break;
                    case 3:
                        res = CommValue[3];
                        list = new List<string>();
                        if (res != null && res.Length == 8)
                        {
                            //计时值
                            Int32 res1 = ByteArrayToInt32(new byte[4] { res[0], res[1], res[2], res[3] });
                            list.Add(res1.ToString());
                            Int16 res2 = ByteArrayToInt16(new byte[2] { res[6], res[7] });
                            list.Add(res2.ToString());
                        }
                        CurrentValue[3] = list;
                        break;
                }
            }

        }

        /// <summary>
        /// 委托跨线程更新UI步骤【4】:更新UI的方法。
        /// </summary>
        private void UpdateUI()
        {
            if (CurrentValue.Count == 3)
            {
                //判断该方法是否被主线程调用,也就是创建窗体控件的线程,当控件的InvokeRequired属性为ture时,说明是被主线程以外的线程调用。如果不加判断,会造成异常
                if (this.InvokeRequired)//判断
                {
                    //委托跨线程更新UI步骤【5】:激活委托。
                    this.Invoke(updateGUI);
                }
                else
                {
                    if (CurrentValue[1].Count>0)
                    {
                        this.txt_1stNum.Text = CurrentValue[1][0];
                        this.cmb_1stNum.Text = CurrentValue[1][1];
                    }
                    if (CurrentValue[2].Count > 0)
                    {
                        this.txt_2ndNum.Text = CurrentValue[2][0];
                        this.cmb_2ndNum.Text = CurrentValue[2][1];
                    }
                    if (CurrentValue[3].Count > 0)
                    {
                        this.txt_3rdNum.Text = CurrentValue[3][0];
                        this.cmb_3rdNum.Text = CurrentValue[3][1];
                    }
                }
            }
        }



        /// <summary>
        /// 4个字节转换成一个长整形
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        private Int32 ByteArrayToInt32(byte[] byteArray)
        {
            if (byteArray.Length == 4)
            {
                return (Int32)(byteArray[3] + byteArray[2] * Math.Pow(2, 8) + byteArray[1] * Math.Pow(2, 16) + byteArray[0] * Math.Pow(2, 24));
            }
            else
            {
                return 0;
            }

        }

        private Int16 ByteArrayToInt16(byte[] byteArray)
        {
            if (byteArray.Length == 2)
            {
                return (Int16)(byteArray[1] + byteArray[0] * Math.Pow(2, 8));
            }
            else
            {
                return 0;
            }

        }

        private void btn_Set1_Click(object sender, EventArgs e)
        {
            objMod.PreSetKeepReg(1, 3, int.Parse(this.txt_Set1.Text.Trim()));
        }

        private void btn_Set2_Click(object sender, EventArgs e)
        {
            objMod.PreSetKeepReg(2, 3, int.Parse(this.txt_Set2.Text.Trim()));
        }

        private void btn_Set3_Click(object sender, EventArgs e)
        {
            objMod.PreSetKeepReg(3, 3, int.Parse(this.txt_Set3.Text.Trim()));
        }
    }
}

  



这篇关于C#--Modbus-一主多从-委托跨线程更新UI界面的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程