2012-01-25 46 views
5

我尝试为事件处理程序订阅数据接收事件。好像我不能指定事件处理函数名称。我不明白为什么
myComPort.DataReceived + = new SerialDataReceivedEventHandler(comPort_DataReceived);给我错误信息。 这是问题,希望任何人都可以回答。在main()中为串行端口添加事件处理程序

a busy cat http://img827.imageshack.us/img827/5904/20120125102247.png

a busy cat http://img444.imageshack.us/img444/3855/20120125102202.png

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); 
      } 
     } 

    } 

    } 

回答

4

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

此外,您的注释注意到SerialPort类有一个托管资源,它需要使用IDisposable/Using模式进行处理,但是您没有包含访问通信端口的使用块。

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

6

首先,由于方法Main是静态的,因此只能调用同一个类中的其他静态方法。正因为如此,comPort_DataReceived被声明为实例方法,下面的代码应该可以解决该事件处理程序的分配:

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

其次,由于myComPortMain定义,它不会在comPort_DataReceived可见。你有两个选择:要么宣布myComPort作为类的静态成员,或使用事件处理程序的sender说法:

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

用于投射发件人+1。一些重构可能会更好,但是发送者的原则对于了解任何事件的使用是非常有用的。 – Chris

+0

如果你想要一个遵循OOP原则的正确的C#程序,相当重要的重构是绝对必要的。我也忽略了其他实例方法和变量仍然会成为问题的事实,我试图保持答案的教学,而不是仅仅提供我自己使用的代码,因此需要进一步研究;) – madd0

+0

因此,声明一个方法静态使它属于一个类型而不是一个实例,对吗?如果是这样,我们是否应该始终将事件处理程序声明为静态?我猜如果我把mycomport作为类的成员,那么它应该对所有的方法都可见,对吗? – fiftyplus

0

Tetsujin no Oni的答案是与范围来处理您的问题的理想方式。这也适用另一种方法是声明myComPort为你的程序的静态成员,例如:

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

然后只是简单地从main方法去除myComPort声明。

+0

但是,哦,你可以创建进入这种习惯的线程问题。 –

+0

@TetsujinnoOni当然 - 我并不是建议OP让它成为一种习惯:)我已经编写了足够的基于套接字的应用程序来知道在单个线程上发生死锁是多么痛苦。 –

+0

因为OP提到了C#的新特性,所以我想确保对这个问题有所了解。 –

相关问题