当前位置:编程学习 > C#/ASP.NET >>

BeginInvoke & serialport 问题

我添加了一个serialport 控件:

// 添加事件
 this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataRec);

// 处理
private void serialPort1_DataRec(object sender, SerialDataReceivedEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new EventArgsDelegate(serialPort1_DataRec), new object[] { sender, e });
                return;
            }

            int d;
            if (RunState)
            {
                GetSerData(serialPort1, cmdA);
            }
            else
            {
                while (serialPort1.BytesToRead != 0)
                {
                    d= serialPort1.ReadByte();
                }
            }
        }

因为this.BeginInvoke(new EventArgsDelegate(serialPort1_DataRec), new object[] { sender, e }); 一直触发,所以new了很多EventArgsDelegate(serialPort1_DataRec),从而导致内存不足, 谁有什么解决方法吗?可以去读一下.net什么变量 从而频繁BeginInvoke。 说白了 就是希望主线程运行完了,在调用BeginInvoke。 --------------------编程问答-------------------- 你就是 那样写的,当然 了 --------------------编程问答-------------------- 以现在的方法写,有没有什么方法补救? 必然加一个什么标志,或者读一个什么.net变量啥的。给意见,而不是写一句废话。 --------------------编程问答-------------------- 没看懂楼主的意思和需求
你那本来就是接收事件了
没必要再判断那些什么串口是否有数据,什么标志位的
只要就有数据他会根据你设置的多少字节触发接收事件而自动去触发该事件的 --------------------编程问答-------------------- 只要有数据通过串口发送就能自动触发serialPort1_DataRec事件,楼主是有什么特殊要求吗?要不然为会在事件里面一直在重新触发事件呢 --------------------编程问答-------------------- 我也就前两天才开始接触C#, 我以为这样写 以为大家都能了解了...  因为serialport 应该是比较常用的。

1)// 添加事件
 this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataRec);
有数据的时候,会自动触发serialPort1_DataRec, 但是这是运行在一个辅助的线程(是系统自己开的一个线程)。

2) 接收到的数据需要在界面显示,这个是运行在UI 线程。

3)c# 指示,数据要传到UI线程显示,必须用BeginInvoke 或者Invoke,不然是不安全的。

谁能介绍一下,你们写C# 串行口代码用的是什么方法? 开定时器自动查询?  --------------------编程问答-------------------- 直接在接收事件里读取串口就行了,有数据过来并且达到了触发字节数量的要求就会触发接收事件,没必要再去判断bytesToRead是否大于0。要是想把接收到的数据显示在界面上,直接用委托就行了 --------------------编程问答-------------------- //按照你自己的要求去改下面的代码
public partial class Form1 : Form {
        private int sn = 1;
        private delegate void AddRecord(ListViewItem lvi);
        private Zd2911Monitor listener;

        public Form1() {
            InitializeComponent();
        }

        private void AddRecordToListView(ListViewItem lvi) {
            lvw_Logs.Items.Add(lvi);
        }

        private void Form1_Load(object sender, EventArgs e) {
            string[] serialName = SerialPort.GetPortNames();
            if (null != serialName) {
                foreach (string name in serialName) {
                    cbo_Comm.Items.Add(name);
                }
                cbo_Comm.SelectedIndex = 0;
            }

            cbo_Baudrate.SelectedIndex = cbo_Baudrate.Items.Count - 1;
        }

        private void btn_Listen_Click(object sender, EventArgs e) {
            if (-1 == cbo_Comm.SelectedIndex || -1 == cbo_Baudrate.SelectedIndex) {
                return;
            }

            try {
                if (btn_Listen.Text.Trim().Equals("监听")) {
                    Monitor m = new Monitor();
                    m.Mode = 1;
                    m.SerialPort = Convert.ToInt32(cbo_Comm.SelectedItem.ToString().Replace("COM", string.Empty));
                    m.SerialBaudRate = Convert.ToInt32(cbo_Baudrate.SelectedItem);
                    listener = Zd2911Monitor.CreateZd2911Monitor(m);
                    listener.ReceiveHandler += new ReceiveHandler(listener_ReceiveHandler);
                    if (listener.OpenListen()) {
                        btn_Listen.Text = "取消";
                    } else {
                        MessageBox.Show("启动监听错误", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                } else {
                    listener.CloseListen();
                    listener = null;
                    btn_Listen.Text = "监听";
                }
            } catch (Exception ex) {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void listener_ReceiveHandler(object sender, ReceiveEventArg e) {
            Record record = e.record;
            string verify = ConvertObject.IOMode(record.Verify);
            string action = ConvertObject.GLogType(record.Action);
            ListViewItem lvi = new ListViewItem(new string[]{sn.ToString(), record.DN.ToString(), record.DIN.ToString(),
                verify, action, record.Clock.ToString("yyyy-MM-dd HH:mm:ss")});
            /*
                 * SerialPort.DataReceived事件运行比较特殊,其运行在辅线程,不能与主线程中的显示数据控件直接进行数据传输,
                 * 如果要与主线程中的显示数据控件直接进行数据传输必须采用创建主线程的异步方法进行数据传输
                 */
            BeginInvoke(new AddRecord(AddRecordToListView), new object[] { lvi });
            sn++;
        }
    } --------------------编程问答--------------------
引用 7 楼 xiaozhi797 的回复:
//按照你自己的要求去改下面的代码
public partial class Form1 : Form {
        private int sn = 1;
        private delegate void AddRecord(ListViewItem lvi);
        private Zd2911Monitor listener;

……
--------------------编程问答--------------------
引用 6 楼 leafmao 的回复:
直接在接收事件里读取串口就行了,有数据过来并且达到了触发字节数量的要求就会触发接收事件,没必要再去判断bytesToRead是否大于0。要是想把接收到的数据显示在界面上,直接用委托就行了


美女,你要知道,串行口送来大量的数据, 需要分析数据,然后在显示, 仅仅只用委托够吗??

1) 在什么地方调用这个委托函数?
2)及时性好吗?

难道大家很少用这样的方法接收串行口数据吗? --------------------编程问答--------------------
引用 9 楼 cyanlin2011 的回复:
引用 6 楼 leafmao 的回复:直接在接收事件里读取串口就行了,有数据过来并且达到了触发字节数量的要求就会触发接收事件,没必要再去判断bytesToRead是否大于0。要是想把接收到的数据显示在界面上,直接用委托就行了

美女,你要知道,串行口送来大量的数据, 需要分析数据,然后在显示, 仅仅只用委托够吗??

1) 在什么地方调用这个委托函数?
2)及时……


把你先分析,分析后再显示啊,额,可能你做的太高端了我没做过。
我现在做的是先发送指令,然后才从串口接收到信息,如果想把接收到的信息显示在UI界面上就用委托,因为是跨线程了只能用委托。我一次发送的内容比较少,采用一问一答的方式。
但是你真没必要判断BytesToRead是否大于0,既然触发了DataReceived事件,肯定是大于0的
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,