【问题标题】:Serial port data received event in separate class from the form串行端口数据接收事件在与表单不同的类中
【发布时间】:2013-02-06 22:43:47
【问题描述】:

我正在使用 Windows 应用程序表单从串行端口接收数据。在表格内我可以提出SerialportDataReceived 事件。但我想要的是把串口事件放在一个单独的类中,并将数据返回到表单中。

这是包含eventhandler的类,用于串口接收数据:

class SerialPortEvent
{
    public void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            SerialPort sp = new SerialPort();
            //no. of data at the port
            int ByteToRead = sp.BytesToRead;

            //create array to store buffer data
            byte[] inputData = new byte[ByteToRead];

            //read the data and store
            sp.Read(inputData, 0, ByteToRead);

        }
        catch (SystemException ex)
        {
            MessageBox.Show(ex.Message, "Data Received Event");
        }


    }
}

收到数据后如何将此类链接到表单?我必须在主程序中还是在表单本身中提出事件?

我现在调用的方式主要如下:

    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());

        SerialPort mySerialPort = new SerialPort("COM81");
        SerialPortEvent ReceivedData = new SerialPortEvent();
        mySerialPort.DataReceived += new SerialDataReceivedEventHandler(ReceivedData.mySerialPort_DataReceived);
        myserialPort.open();
    }

串口收到事件没有收到任何内容。

我做错了什么吗?

【问题讨论】:

  • 不要抓到SystemException。改为捕获Exception。另外,如果您想真正了解发生了什么,请显示ex.ToString()
  • 您不会从 new SerialPort 对象中读取太多内容。将 sender 转换为 SerialPort 以使用实际生成事件的实例。

标签: c# events event-handling


【解决方案1】:

让您的其他类定义它自己的事件以供表单处理,该事件可以为表单提供读取的字节:

class SerialPortEvent
{
    private SerialPort mySerialPort;

    public Action<byte[]> DataReceived;

    //Created the actual serial port in the constructor here, 
    //as it makes more sense than having the caller need to do it.
    //you'll also need access to it in the event handler to read the data
    public SerialPortEvent()
    {
        mySerialPort = new SerialPort("COM81");
        mySerialPort.DataReceived += mySerialPort_DataReceived
        myserialPort.open();
    }

    public void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            //no. of data at the port
            int ByteToRead = mySerialPort.BytesToRead;

            //create array to store buffer data
            byte[] inputData = new byte[ByteToRead];

            //read the data and store
            mySerialPort.Read(inputData, 0, ByteToRead);

            var copy = DataReceived;
            if(copy != null) copy(inputData);

        }
        catch (SystemException ex)
        {
            MessageBox.Show(ex.Message, "Data Received Event");
        }
    }
}

接下来,您不想在Main 中创建SerialPortEvent 实例,而是要在主窗体的构造函数或加载事件中创建它:

public Form1()
{
    SerialPortEvent serialPortEvent = new SerialPortEvent();
    serialPortEvent.DataReceived += ProcessData;
}

private void ProcessData(byte[] data)
{
    //TODO do stuff with data
}

【讨论】:

  • 感谢Servy。这是一个逻辑解决方案.. 但mySerialPort_DataReceived 方法出现错误:object reference not set to an instance of an object
  • @Liban 您需要更具体地说明错误出现在哪一行。
  • 在第一行。当程序开始执行第一行 int ByteToRead = mySerialPort.BytesToRead; 时,它会抛出异常消息:object reference not set to an instance of an object
  • @Liban 你对代码做了什么改动吗?因为不可能抛出该异常,因为该对象在构造函数中初始化并且从未重新分配。
猜你喜欢
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
  • 1970-01-01
相关资源
最近更新 更多