2010-02-17 1 views
5

Ho un'app di prova WPF per valutare la comunicazione della porta seriale basata su eventi (rispetto al polling della porta seriale). Il problema è che l'evento DataReceived non sembra affatto sparare.Data SerialPort DataReceived evento non attivato

Ho un modulo WPF molto semplice con un TextBox per l'input dell'utente, un TextBlock per l'output e un pulsante per scrivere l'input sulla porta seriale.

Ecco il codice:

public partial class Window1 : Window 
{ 
    SerialPort port; 

    public Window1() 
    { 
     InitializeComponent(); 

     port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One); 
     port.DataReceived += 
      new SerialDataReceivedEventHandler(port_DataReceived); 
     port.Open(); 
    } 

    void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     Debug.Print("receiving!"); 
     string data = port.ReadExisting(); 
     Debug.Print(data); 
     outputText.Text = data; 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Debug.Print("sending: " + inputText.Text); 
     port.WriteLine(inputText.Text); 
    } 
}

Ora, qui ci sono i fattori di complicazione:

  1. Il computer portatile su cui sto lavorando non ha porte seriali, quindi sto utilizzando un pezzo di software chiamato Virtual Serial Port Emulator per configurare una COM2. VSPE ha funzionato egregiamente in passato, e non è chiaro il motivo per cui si guasterebbe solo con la classe SerialPort di .NET, ma ne parlo per ogni evenienza.

  2. Quando si preme il pulsante del modulo per inviare i dati, la finestra di Hyperterminal (collegata a COM2) indica che i dati stanno passando. Sì, disconnetto Hyperterminal quando voglio testare la capacità del mio modulo di leggere la porta.

  3. Ho provato ad aprire la porta prima di collegare l'evento. Nessun cambiamento.

Ho letto un altro post qui dove qualcun altro ha riscontrato un problema simile. Nessuna di queste informazioni mi ha aiutato in questo caso.

EDIT:

Ecco la versione console (modificato da http://mark.michaelis.net/Blog/TheBasicsOfSystemIOPortsSerialPort.aspx):

class Program 
{ 
    static SerialPort port; 

    static void Main(string[] args) 
    { 
     port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One); 
     port.DataReceived += 
      new SerialDataReceivedEventHandler(port_DataReceived); 
     port.Open(); 

     string text; 
     do 
     { 
      text = Console.ReadLine(); 
      port.Write(text + "\r\n"); 
     } 
     while (text.ToLower() != "q"); 
    } 

    public static void port_DataReceived(object sender, 
     SerialDataReceivedEventArgs args) 
    { 
     string text = port.ReadExisting(); 
     Console.WriteLine("received: " + text); 
    } 
}

Questo dovrebbe eliminare qualsiasi preoccupazione che si tratta di un problema di threading (credo). Questo non funziona neanche. Anche in questo caso, Hyperterminal riporta i dati inviati attraverso la porta, ma l'app della console non sembra attivare l'evento DataReceived.

EDIT # 2:

mi sono reso conto che avevo due applicazioni separate che dovrebbero inviare e ricevere dalla porta seriale, così ho deciso di provare a loro in esecuzione contemporaneamente ...

Se io digitare nell'app della console, l'evento DataReceived dell'app WPF si attiva, con l'errore di thread previsto (che so come gestire).

Se si digita nell'app WPF, l'evento DataReceived dell'app della console viene attivato e riecheggia i dati.

Immagino che il problema sia da qualche parte nel mio utilizzo del software VSPE, che è configurato per il trattamento di una porta seriale come input e output. E attraverso alcune stranezze della classe SerialPort, un'istanza di una porta seriale non può essere sia il mittente che il destinatario. Ad ogni modo, penso che sia risolto.

risposta

0

posso solo supporre che il problema era effettivamente con il virtuale Programma di emulazione porta seriale. questo NON è per dire che c'è un problema con quel software: VSPE ha funzionato molto bene per me finora. Ma c'era un conflitto tra il mio codice e come avevo impostato il connettore VSPE.

3

Non posso dirlo con certezza, ma potrebbe esserci un problema di threading. WPF gestisce il threading in modo diverso, e il polling della porta virtuale è asincrono, credo. Hai provato questo con un'applicazione Windows Form o console per dimostrare che può funzionare a tutti?

+0

Vedere la versione della console in alto. Senza fortuna. – Klay

2

Io uso la stessa identica configurazione, funziona perfettamente ora ma ho dovuto risolvere molti problemi per arrivarci.

Ecco perché la mia dichiarazione iniziale assomiglia:

comControl = new SerialPort(); 

//This is important - determine your min nb of bytes at which you will fire your event, mine is 9 
comControl.ReceivedBytesThreshold = 9; 

//register the event handlers 
comControl.DataReceived += new SerialDataReceivedEventHandler(OnReceive); 
comControl.PinChanged += new SerialPinChangedEventHandler(OnPinChanged); 

io seperated la porta aperta e chiudere i metodi di porta dal momento che posso controllare spesso se la porta COM è stato chiuso.

public bool OpenPort() 
{ 
    try 
    { 
     //must keep it open to maintain connection (CTS) 
     if (!comControl.IsOpen) 
     { 
      comControl.Open(); 
      comControl.RtsEnable = true; 
     } 
    } 
    catch (Exception e) 
    { 
     //error handling here 
    } 
} 

Infine, verificare che il driver della porta COM virtuale sia installato correttamente e che si sta utilizzando la porta a destra, un plug and play per il mio adattatore non è stato sufficiente. Se si desidera creare una sorta di controllo che vi permetterà di scegliere le porte disponibili in fase di esecuzione, il seguente comando vi darà le porte disponibili:

System.IO.Ports.SerialPort.GetPortNames() 
+0

Dopo la modifica, vedo che hai risolto alcuni nodi, ma hai detto che "E attraverso alcune stranezze della classe SerialPort, un'istanza di una porta seriale non può essere sia il mittente che il destinatario" Questo non è vero. La classe SerialPort può essere sia il mittente che il destinatario. Dal momento che tu affermi che le cose sembrano funzionare in qualche modo, non mi dilungherò :) – Roast

+0

Bene, allora sicuramente sembra che la stranezza non sia nella classe SerialPort, ma nell'accoppiamento con il software della porta seriale virtuale. – Klay

+0

+1 - L'impostazione del pin RTS su Abilitato era qualcosa che avevo dimenticato. Ho dimenticato il controllo del flusso hardware. –

0

Ho avuto un problema simile quando si esegue un tale driver da un modulo, anche se nessun VSPE è solo un semplice SP. Crediamo che questo fosse un problema con il modello STA visto che lo spostamento verso l'inclusione in un'app per console è stato risolto abbastanza.

0

Anche io uso VSPE! Funziona meravigliosamente .. Stavo avendo lo stesso problema e il modo in cui l'ho risolto era di rendere le due porte COM un PAIR in VSPE invece di creare solo due porte com virtuali

0

Recentemente mi sono imbattuto in un problema altrettanto strano, ma solo su alcune macchine. Come notato da Dave Swersky, questo potrebbe essere stato un problema di threading, specialmente se si eseguiva .NET 4.0 o versioni successive.

In .NET 4.0 il gestore eventi viene attivato su un thread ThreadPool e in determinate circostanze potrebbe verificarsi un notevole ritardo prima che si verifichi. (Nel mio codice, che funzionava perfettamente sotto .NET 2.0, sono stati rilevati problemi non appena abbiamo eseguito l'aggiornamento a .NET 4.5. Il gestore di eventi sarebbe stato attivato più tardi di quanto ci si sarebbe aspettato, ea volte non sarebbe stato attivato a tutto!)

La chiamata a ThreadPool.SetMinThreads(...) con un valore maggiore per i thread di completamento ha risolto il problema con la stessa rapidità con cui era arrivato. Nel contesto della nostra applicazione ThreadPool.SetMinThreads(2, 4) era sufficiente. Sulle macchine in cui è stato osservato il problema, i valori di default (come ottenuto chiamando ThreadPool.SetMinThreads) erano entrambi 2.

7
port.DtrEnable = true; 

Ciò ha risolto per me, la bandiera DataTransmitReady non è stato abilitato, in modo che nessun dato è stato ricevuto.

+1

Questo ha funzionato anche per me dopo 5 scrupolose ore di incasinamento con una bilancia collegata a un tablet. Il saldo di una compagnia (OHaus) stava comunicando la multa senza questa linea, il saldo della compagnia successiva (Sartorius) non lo era. – jaredbaszler

0

Due giorni fa ho avuto lo stesso problema ed era un grosso problema perché avevo bisogno di consegnare l'app oggi. Quindi .. dopo troppa googleashion ho supposto che il problema fosse un'altra cosa e non il mio codice.

La mia soluzione era uninstall McAfee antivirus e tutte le cose relative a questo. Quando ho visto i registri di McAfee ha registrato record sui thread di stop e ho ipotizzato che lo SerialDataReceivedEventHandler() eseguisse una discussione.

Spero che questa soluzione funzioni per voi. Saluti.