2012-01-25 54 views
5

Tôi cố gắng đăng ký trình xử lý sự kiện cho sự kiện nhận dữ liệu. Có vẻ như tôi không thể chỉ định tên chức năng xử lý sự kiện. Tôi không hiểu tại sao
myComPort.DataReceived + = new SerialDataReceivedEventHandler (comPort_DataReceived); đang cho tôi thông báo lỗi. Đây là vấn đề, hy vọng mọi người có thể trả lời.Thêm trình xử lý sự kiện vào main() cho SerialPort

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

    } 

    } 

Trả lời

4

Trong xử lý sự kiện của bạn, myComPort không nằm trong phạm vi - nó tuyên bố tại địa phương trong phương pháp main() của bạn. Tôi sẽ đề nghị bạn giải nén việc xử lý cổng com vào một lớp và làm cho myComPort trở thành một biến thành viên của lớp đó.

Ngoài ra, nhận xét của bạn lưu ý rằng lớp SerialPort có tài nguyên được quản lý mà nó cần phải loại bỏ sử dụng mẫu IDisposable/Using, nhưng bạn không có khối sử dụng truy cập vào cổng comm.

Cuối cùng, phương thức bạn đang thêm làm trình xử lý sự kiện tồn tại dưới dạng thành viên đối tượng chứ không phải là thành viên tĩnh; để truy cập nó từ phạm vi tĩnh của phương thức main(), bạn cần lấy nó từ một thể hiện của lớp hoặc làm cho phương thức tĩnh.

6

Đầu tiên, vì phương thức Main là tĩnh, bạn chỉ có thể gọi các phương thức tĩnh khác trong cùng một lớp. Vì nó là, comPort_DataReceived được khai báo là một phương pháp dụ, đoạn mã sau sẽ khắc phục sự phân công của xử lý sự kiện:

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

Thứ hai, kể từ myComPort được định nghĩa trong Main, nó sẽ không được hiển thị trong comPort_DataReceived. Bạn có hai lựa chọn: hoặc tuyên bố myComPort như một thành viên tĩnh của lớp học của bạn, hoặc sử dụng các sender đối số của các xử lý sự kiện:

câu trả lời
static void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    SerialPort port = (SerialPort)sender; 
    // ... 
} 
+4

+1 để truyền người gửi. Một số tái cấu trúc có thể tốt hơn nhưng nguyên tắc đúc người gửi là rất hữu ích để biết về bất kỳ sự kiện sử dụng nào. – Chris

+0

refactoring khá quan trọng là dứt khoát cần thiết nếu bạn muốn có một chương trình C# phù hợp theo nguyên tắc OOP. Tôi cũng bỏ qua thực tế rằng các phương pháp và biến thể hiện khác vẫn sẽ là một vấn đề, tôi cố gắng giữ cho câu trả lời sư phạm thay vì chỉ cung cấp mã mà tôi đã sử dụng bản thân mình, vì vậy cần nghiên cứu thêm một chút;) – madd0

+0

phương thức tĩnh làm cho nó thuộc về một kiểu thay vì một cá thể, đúng không? nếu vậy, chúng ta có nên luôn khai báo trình xử lý sự kiện là tĩnh không? Tôi đoán nếu tôi đặt mycomport như là một thành viên của lớp, sau đó nó sẽ hiển thị cho tất cả các phương pháp, phải không? – fiftyplus

0

Tetsujin no Oni 's là cách lý tưởng để giải quyết vấn đề của bạn với phạm vi. Một phương pháp khác cũng làm việc là để khai báo myComPort như một thành viên tĩnh của chương trình của bạn, ví dụ .:

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

Sau đó chỉ cần loại bỏ các tuyên bố myComPort từ phương pháp main của bạn.

+0

Nhưng vấn đề luồng mà bạn có thể tạo ra trong thói quen đó. –

+0

@TetsujinnoOni Tất nhiên - Tôi không gợi ý rằng OP làm cho nó trở thành một thói quen :) Tôi đã viết đủ các ứng dụng dựa trên socket để biết làm thế nào đau đớn là có deadlocks trên một sợi đơn. –

+0

Tôi muốn chắc chắn rằng đã có nhận thức về vấn đề này, vì OP đã đề cập là mới đối với C#. –

Các vấn đề liên quan