在 SerialPort 的 main() 中添加事件处理程序

问题描述 投票:0回答:3

我尝试将事件处理程序订阅到数据接收事件。似乎我无法指定事件处理程序函数名称。我不明白为什么

myComPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived); 

给我错误信息。

问题就在这里,希望大家能解答。

namespace serialport
{
    public class Program
    {

        internal List<Byte> portBuffer = new List<Byte>(1024);

        static void Main()
        {


            //1. find available COM port
            string[] nameArray = null;
            string myComPortName = null;
            nameArray = SerialPort.GetPortNames();
            if (nameArray.GetUpperBound(0) >= 0)
            {
                myComPortName = nameArray[0];
            }
            else
            {
                Console.WriteLine("Error");
                return;
            }


            //2. create a serialport object
            // the port object is closed automatically by use using()
            SerialPort myComPort = new SerialPort();
            myComPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
            myComPort.PortName = myComPortName;
            //the default paramit are 9600,no parity,one stop bit, and no flow control



            //3.open the port
            try
            {
                myComPort.Open();
            }
            catch (UnauthorizedAccessException ex)
            {
                MessageBox.Show(ex.Message);
            }
            //Add timeout, p161

            //reading Bytes
            byte[] byteBuffer = new byte[10];
            Int32 count;
            Int32 numberOfReceivedBytes;
            myComPort.Read(byteBuffer, 0, 9);
            for (count = 0; count <= 3; count++)
            {
                Console.WriteLine(byteBuffer[count].ToString());
            }


        }
        //The event handler should be static??
        void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int numberOfBytesToRead;
            numberOfBytesToRead = myComPort.BytesToRead;
            byte[] newReceivedData = new byte[numberOfBytesToRead];
            myComPort.Read(newReceivedData, 0, numberOfBytesToRead);
            portBuffer.AddRange(newReceivedData);
            ProcessData();
        }
        private void ProcessData()
        {
            //when 8 bytes have arrived, display then and remove them from the buffer
            int count;
            int numberOfBytesToRead = 8;

            if (portBuffer.Count >= numberOfBytesToRead)
            {
                for (count = 0; count < numberOfBytesToRead; count++)
                {
                    Console.WriteLine((char)(portBuffer[count]));
                }
                portBuffer.RemoveRange(0, numberOfBytesToRead);
            }
        }

    }

    }
c# event-handling idisposable
3个回答
6
投票

首先,由于方法

Main
是静态的,因此只能调用同一个类中的其他静态方法。事实上,
comPort_DataReceived
被声明为实例方法,以下代码应该修复事件处理程序的分配:

static void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   // ...
}

其次,由于

myComPort
是在
Main
中定义的,所以它在
comPort_DataReceived
中是不可见的。您有两种选择:要么将
myComPort
声明为类的静态成员,要么使用事件处理程序的
sender
参数:

static void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort port = (SerialPort)sender;
    // ...
}

4
投票

在您的事件处理程序中,myComPort 不在范围内 - 它是在您的 main() 方法中本地声明的。我建议您将 com 端口处理提取到一个类中,并使 myComPort 成为该类的成员变量。

此外,您的评论指出 SerialPort 类有一个托管资源,需要使用 IDisposable / using 模式来处理该资源,但您没有使用块来包装对通信端口的访问。

最后,您添加为事件处理程序的方法作为实例成员而不是静态成员存在;要从 main() 方法的静态范围访问它,您需要从类的实例中获取它或使该方法静态。


0
投票

Tetsujin no Oni 的答案是处理范围问题的理想方法。另一种可行的方法是将

myComPort
声明为程序的静态成员,例如:

internal List<Byte> portBuffer = new List<Byte>(1024);
private SerialPort myComPort = new SerialPort();

然后只需从

myComPort
方法中删除
main
声明即可。

© www.soinside.com 2019 - 2024. All rights reserved.