目前碰上个问题:我要操作两个串口,串口的返回数据是通过事件获得的。
但是我要在一个操作中连续向串口写数据,然后查看返回数据,以实现操作。这样就存在线程问题。头一次处理类似问题,大家看看在现在的代码情况下如何处理。代码如下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;namespace Termie
{
    public partial class frmMain : Form
    {
        string RevInto, RevMag;        /// <summary>
        /// If character 0-9 a-f A-F, then return hex digit value ?
        /// </summary>
        private static int GetHexDigit(char c)
        {
            if ('0' <= c && c <= '9') return (c - '0');
            if ('a' <= c && c <= 'f') return (c - 'a') + 10;
            if ('A' <= c && c <= 'F') return (c - 'A') + 10;
            return 0;
        }
        /// <summary>
        /// Parse states for ConvertEscapeSequences()
        /// </summary>
        public enum Expecting : byte
        {
            ANY = 1,
            ESCAPED_CHAR,
            HEX_1ST_DIGIT,
            HEX_2ND_DIGIT
        };        public frmMain()
        {
            InitializeComponent();            Settings.Read();
            TopMost = Settings.Option.StayOnTop;            // let form use multiple fonts            PortInto comInto = PortInto.Instance;
            comInto.StatusChanged += OnIntoStatusChanged;
            comInto.DataReceived += OnIntoDataReceived;                        PortMag comMag = PortMag.Instance;
            comMag.StatusChanged += OnMagStatusChanged;
            comMag.DataReceived += OnMagDataReceived;                        RevInto ="";
            RevMag = "";
        }        internal delegate void StringDelegate(string data);        //传入值转码
        private string ConvertEscapeSequences(string s)
        {
            Expecting expecting = Expecting.ANY;            int hexNum = 0;
            string outs = "";
            foreach (char c in s)
            {
                switch (expecting)
                {
                    case Expecting.ANY:
                        if (c == '\\')
                            expecting = Expecting.ESCAPED_CHAR;
                        else
                            outs += c;
                        break;
                    case Expecting.ESCAPED_CHAR:
                        if (c == 'x')
                        {
                            expecting = Expecting.HEX_1ST_DIGIT;
                        }
                        else
                        {
                            char c2 = c;
                            switch (c)
                            {
                                case 'n': c2 = '\n'; break;
                                case 'r': c2 = '\r'; break;
                                case 't': c2 = '\t'; break;
                            }
                            outs += c2;
                            expecting = Expecting.ANY;
                        }
                        break;
                    case Expecting.HEX_1ST_DIGIT:
                        hexNum = GetHexDigit(c) * 16;
                        expecting = Expecting.HEX_2ND_DIGIT;
                        break;
                    case Expecting.HEX_2ND_DIGIT:
                        hexNum += GetHexDigit(c);
                        outs += (char)hexNum;
                        expecting = Expecting.ANY;
                        break;
                }
            }
            return outs;
        }        /// <summary>
        /// Update the connection status
        /// </summary>
        public void OnIntoStatusChanged(string status)
        {
            //Handle multi-threading
            if (InvokeRequired)
            {
                Invoke(new StringDelegate(OnIntoStatusChanged), new object[] { status });
                return;
            }            txtInfo.AppendText("端口A状态:" + status + "\r\n");
            txtInfo.ScrollToCaret();
        }        /// <summary>
        /// Update the connection status
        /// </summary>
        public void OnMagStatusChanged(string status)
        {
            //Handle multi-threading
            if (InvokeRequired)
            {
                Invoke(new StringDelegate(OnMagStatusChanged), new object[] { status });
                return;
            }            txtInfo.AppendText("端口B状态:" + status + "\r\n");
            txtInfo.ScrollToCaret();
        }        public void OnIntoDataReceived(string dataIn)
        {
            //Handle multi-threading
            if (InvokeRequired)
            {
                Invoke(new StringDelegate(OnIntoDataReceived), new object[] { dataIn });
                return;
            }            if (dataIn.EndsWith("D"))
            {
                if (dataIn.StartsWith("C"))
                {
                    RevInto = dataIn;
                }
                else
                {
                    RevInto += dataIn;
                }                txtInfo.AppendText("端口A接收数据:" + RevInto + "\r\n");
                txtInfo.ScrollToCaret();
            }
            else if (dataIn.StartsWith("C"))
            {
                RevInto = dataIn;
            }
            else
            {
                RevInto += dataIn;
            }            
        }        public void OnMagDataReceived(string dataIn)
        {
            //Handle multi-threading
            if (InvokeRequired)
            {
                Invoke(new StringDelegate(OnMagDataReceived), new object[] { dataIn });
                return;
            }
            
            txtInfo.AppendText("端口B接收数据:" + dataIn + "\r\n");
        }        private void btPortConn_Click(object sender, EventArgs e)
        {
            PortInto comInto = PortInto.Instance;
            PortMag comMag = PortMag.Instance;            if (!comInto.IsOpen)
                comInto.Open();            if (!comMag.IsOpen)
                comMag.Open();            string command = "AK" + (char)0 + "B";
            command = ConvertEscapeSequences(command);
            
            comInto.Send(command);            //这里发送了端口数据,需要等待返回OnIntoDataReceived事件返回数据,请问如何切换线程
            
            if (RevInto == "CE1D")
            {
                MessageBox.Show(RevInto + "端口A联机成功!");
            }
            else
            {
                MessageBox.Show(RevInto + "端口A联机失败!");
                return;
            }            command = (char)2 + "C0132400000000" + (char)3;
            command = ConvertEscapeSequences(command);
            
            comMag.Send(command);
            
        }        private void btSetting_Click(object sender, EventArgs e)
        {
            frmSetting nowFrmSetting = new frmSetting();            nowFrmSetting.ShowDialog();
        }        private void btExit_Click(object sender, EventArgs e)
        {
            PortInto comInto = PortInto.Instance;
            PortMag comMag = PortMag.Instance;            comInto.Close();
            comMag.Close();            
        }        private void btReset_Click(object sender, EventArgs e)
        {        }
    }
}

解决方案 »

  1.   

    你数据分析的地方给个建议:
    串口通讯中,如果不确定数据是否完整有效。不要用字符串方式搜索,这样效率比较低,当然如果你只找一个,系统的IndexOf比你写的高,但协议往往不止一个字符,或一个单词,有连续的规则,看上去很像正则是不是?很遗憾,字符串操作都不推荐用了,正则就更不推荐用了。虽然正则实现了复杂规则。但是正则的回溯机制导致了你搜索的可逆,效率不稳定,极限情况可能导致引擎崩溃而让程序瘫痪。协议分析,尤其是字符串协议分析。你可以考虑自己循环一次来搜索关键字,这样时间复杂度能总是O(n)。