2012-01-25 9 views
5

Provo a sottoscrivere un gestore di eventi all'evento di dati ricevuti. Sembra che non posso specificare il nome della funzione del gestore di eventi. Non capisco perché
myComPort.DataReceived + = new SerialDataReceivedEventHandler (comPort_DataReceived); mi sta dando un messaggio di errore. Ecco il problema, spero che qualcuno possa rispondere.Aggiunta del gestore di eventi in main() per 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); 
      } 
     } 

    } 

    } 

risposta

4

Nel vostro gestore di eventi, myComPort non è di portata - è dichiarato localmente nel metodo main(). Suggerirei di estrarre la gestione della porta COM in una classe e rendere myComPort una variabile membro di quella classe.

Inoltre, i vostri commenti notano che la classe SerialPort ha una risorsa gestita che deve essere eliminata utilizzando lo schema IDisposable/Using, ma non si dispone di un blocco utilizzando l'accesso alla porta di comunicazione.

Infine, il metodo che si sta aggiungendo come gestore di eventi esiste come membro di un'istanza anziché come membro statico; per accedervi dall'ambito statico del metodo main(), è necessario prenderlo da un'istanza della classe o rendere statico il metodo.

6

Innanzitutto, poiché il metodo Main è statico, è possibile chiamare solo altri metodi statici nella stessa classe. Così com'è, comPort_DataReceived è dichiarato come un metodo di istanza, il seguente codice dovrebbe risolvere l'assegnazione del gestore di eventi:

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

In secondo luogo, dal momento che myComPort è definito in Main, non sarà visibile in comPort_DataReceived. Avete due scelte: o dichiarare myComPort come un membro statico della classe, o utilizzare il sender argomento del gestore di eventi:

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

+1 per trasmettere il mittente. Alcuni refactoring potrebbero essere migliori, ma il principio di trasmettere il mittente è enormemente utile per conoscere l'utilizzo di qualsiasi evento. – Chris

+0

il refactoring piuttosto importante è definitivamente necessario se si desidera un programma C# adeguato che segua i principi OOP. Ho anche omesso il fatto che altri metodi e variabili di istanza saranno ancora un problema, ho cercato di mantenere la risposta pedagogica invece di fornire solo il codice che avrei usato io stesso, quindi è necessario un po 'di ulteriore ricerca;) – madd0

+0

Quindi dichiarare un metodo statico fa appartenere a un tipo piuttosto a un'istanza, giusto? in tal caso, dovremmo dichiarare sempre il gestore di eventi come statico? Immagino che se metto mycomport come membro della classe, allora dovrebbe essere visibile a tutti i metodi, giusto? – fiftyplus

0

s' Tetsujin no Oni è il modo ideale per gestire il problema con ambito. Un altro approccio che funziona anche è dichiarare myComPort come un membro statico del vostro programma, per es .:

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

Poi è sufficiente rimuovere la dichiarazione myComPort dal tuo metodo main.

+0

Ma oh, i problemi di threading che potresti creare entrano in quell'abitudine. –

+0

@TetsujinnoOni Ovviamente non stavo suggerendo che l'OP rendesse un'abitudine :) Ho scritto abbastanza app basate su socket per sapere quanto sia doloroso avere deadlock su un singolo thread. –

+0

Volevo essere sicuro che ci fosse consapevolezza del problema, dal momento che l'OP aveva menzionato di essere nuovo in C#. –

Problemi correlati