收到串行数据后,以主窗体触发功能

时间:2017-10-09 17:31:07

标签: c# delegates serial-port nfc invoke

我正在制作一个读取NFC卡上的值的程序。 我有一个类,它读取由连接到NFC IC的EMBED发送的串行通信的值。收到数据后,程序(主表格)必须更改“页面”。并处理数据。 我已将用户控件用作不同的页面'。

我知道有多个线程,我不能在不使用某种Invoke / Deleagate的情况下从不同的线程更改GUI。但是,我不确定如何在我的代码上实现它。

这是我的代码(遗漏了不相关的代码):

SerialData Class

public class SerialData
{
    public SerialPort ComPort;
    public String savedText;

    public SerialData()
    {
        ComPort = new SerialPort();

        // set port data
        ComPort.PortName = "COM5";
        ComPort.BaudRate = 9600;
        ComPort.DataBits = 8;
        ComPort.RtsEnable = true;
        ComPort.DtrEnable = true;
    }

    public void readCard()
    {
        try
        {
            savedText = "";
            ComPort.Open();
            ComPort.DataReceived += ComPort_DataReceived;
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.Message + ex.StackTrace);
        }
    }

    private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        var serialPort = (SerialPort)sender;
        var data = serialPort.ReadExisting();
        savedText += data;
    }
}

Form1代码

public partial class Form1 : Form
{
    List<UserControl> Pages = new List<UserControl>();
    public int CurrentPage = 0;

    SerialData SerialDataDriver = new SerialData();

    public Form1()
    {
        InitializeComponent();

        Pages.Add(page1);
        Pages.Add(page2);
        Pages.Add(page3);

        // change to first page
        ChangeToPage(0);
    }

    private void Page1ButtonClick(object sender, EventArgs e)
    {
        ChangeToPage(1);
        SerialDataDriver.readCard();
    }

    void ComPort_DataReceived(string data)
    {
        SerialDataDriver.ComPort.Close(); /// close ComPort
        ChangeToPage(2);
    }

}

2 个答案:

答案 0 :(得分:0)

您可以使用自定义SerialPortadd访问者创建一个实现remove事件的包装器:

using System;
using System.IO.Ports;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private readonly SerialData _data;

        public Form1()
        {
            InitializeComponent();

            Closing += (sender, args) => { _data.Dispose(); };

            _data = new SerialData(new SerialPort("COM5", 9600));
            _data.DataReceived += Serial_DataReceived;
        }

        private void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            // do something
        }
    }

    public class SerialData : IDisposable
    {
        private readonly object _locker = new object();
        private readonly SerialPort _port;

        public SerialData(SerialPort port)
        {
            _port = port ?? throw new ArgumentNullException(nameof(port));
        }

        #region IDisposable Members

        public void Dispose()
        {
            _port.Dispose();
        }

        #endregion

        public event SerialDataReceivedEventHandler DataReceived
        {
            add
            {
                lock (_locker)
                {
                    _port.DataReceived += value;
                }
            }
            remove

            {
                lock (_locker)
                {
                    _port.DataReceived -= value;
                }
            }
        }
    }
}

答案 1 :(得分:0)

以下是自定义事件的示例:

public class SerialData
{

    public SerialPort ComPort;
    public String savedText;

    public delegate void Data(string message);
    public event Data NewData;

    private void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        var serialPort = (SerialPort)sender;
        var data = serialPort.ReadExisting();
        savedText += data;
        if (NewData != null)
        {
            NewData(savedText);
        }
    }

}

...以及如何以表格形式连接和接收它:

public Form1()
{
    InitializeComponent();

    Pages.Add(page1);
    Pages.Add(page2);
    Pages.Add(page3);

    // change to first page
    ChangeToPage(0);

    SerialDataDriver.NewData += SerialDataDriver_NewData;
}

private void SerialDataDriver_NewData(string message)
{
    if (this.InvokeRequired)
    {
        this.Invoke((MethodInvoker) delegate() {
            SerialDataDriver_NewData(message);
        });
    }
    else
    {
        // do something with "message"
        this.label1.Text = message;
    }
}