In debug funziona tutto ma l'exe no - lettura da seriale

giovedì 10 luglio 2014 - 10.22

gvfbb Profilo | Newbie

salve

ho fatto un programmino molto semplice in c# che mi scrive in una textbox quello che un lettore barcode legge via seriale.
Ho utilizzato la classe SerialPort, mentre non disponendo di una porta seriale nel mio Pc ho utilizzato un convertitore Serial-To_Usb.

In ambiente Visual Studio funziona tutto e la textbox mi viene correttamente compilata.
Se invece eseguo il compilato .exe, la textbox rimane vuota nonostante il barcode mi dia il segnale acustico della lettura avvenuta.

Quale potrebbe essere il problema?

grazie

0v3rCl0ck Profilo | Guru

così non mi viene in mente nulla... solo che in debug, c'è di mezzo un eseguibile host per intercettare tutto il codice in esecuzione, e quindi da una parte rallenta un po' il codice, e in genere la parte multi-threading credo possa essere inficiata in qualche modo.

Altra cosa può dipendere se l'eseguibile che lanci, è in realtà compilato in release invece che debug, e quindi vengono applicate ottimizzazioni di compilazione, che puoi controllare con il flag "Optimize code" dalle proprietà del progetto, nella scheda "Build".

prova a postare anche il codice, perchè non posso neanche chiederti di farmi una console che riproduca il problema, dato che non saprei come simulare il lettore barcode.

EDIT: ho trovato un simulatore semplice, https://github.com/mroach/barcode-simulator anche perchè giustamente come spiega il dev, i barcode reader non fanno altro che farsi vedere al sistema come delle tastiere, e quindi fare un simulatore è abbastanza banale.

Potresti provare con il simulatore, perchè se così funziona, allora a questo punto è qualcosa che dipende dall'hardware / usb-to-serial... e qualcosa del genere, anche se non spiega perchè in debug funziona...




Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

gvfbb Profilo | Newbie

grazie per la disponibilità

ho allegato il codice della form frmMain dove è istanziato un oggetto SerialPort.

Ho provato anche compilando in release, checkando e dececkando l'ottimizzazione codice...ma niente.

La cosa significativa è che se eseguo l'exe non funziona, ma se dall'ambiente di sviluppo faccio Debug -> Attach to Process, e mi attacco
al processo, ricomincia a funzionare

grazie per ora

0v3rCl0ck Profilo | Guru

semplifica un po' il codice per capire se c'è un problema, con qualcosa così:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

aggiunto: button, textbox, statusStrip e una toolStripStatusLabel

e senza chiudere la porta sulla ricezione, prova a vedere se così ti funziona.

poi con il Portmon, puoi anche controllare che effettivamente sulla porta sia passato qualcosa: http://technet.microsoft.com/en-us/sysinternals/bb896644.aspx
Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

gvfbb Profilo | Newbie

carissimo Overclock

grazie anche ai tuoi suggerimenti e ad alcune prove sono arrivato a queste due conclusioni:

- se faccio il ciclo sui byte letti non funziona. O meglio funziona in debug ma non l'exe. Ci vuole il readExisting()
- devo togliere la chiusura della seriale alla fine della lettura, perché altera la lettura stessa

tuttavia il mio programma originale installato su Win7 64 bit ha funzionato correttamente.
Il problema è nato su Win8 64 bit.

Grazie! ora direi che tutto funziona (ho apprezzato anche il modo elegante di utiizzare l'Invoke rispetto a come lo utilizzavo io)

Giovanni

0v3rCl0ck Profilo | Guru

>
>- se faccio il ciclo sui byte letti non funziona. O meglio funziona
>in debug ma non l'exe. Ci vuole il readExisting()

l'avevo puramente copiato da msdn, per facilitare la cosa, senza preoccuparmi di cosa faceva il tuo codice, che sembrava fare qualcosa di più sofisticato, se ti è bastato il ReadExisting() moooolto meglio

>- devo togliere la chiusura della seriale alla fine della lettura,
>perché altera la lettura stessa

si quello definitivamente non serve, credo tu possa tenere sempre aperta la connessione fino a che la schermata è aperta, dovresti vedere cosa succede togliendo e rimettendo il lettore, per capire se la libreria gestisce la cosa silentemente, o ti spara una bella eccezione che devi gestire e riaprire la connessione.

>
>tuttavia il mio programma originale installato su Win7 64 bit
>ha funzionato correttamente.
>Il problema è nato su Win8 64 bit.
>

su questo proprio non saprei, mistero della fede

>Grazie! ora direi che tutto funziona (ho apprezzato anche il
>modo elegante di utiizzare l'Invoke rispetto a come lo utilizzavo
>io)

si l'Invoke di fatto è IL metodo per eccellenza, anche il SynchronizationContext di winforms (WindowsFormsSynchronizationContext), che è alla base del pattern async/await, sfrutta proprio l'Invoke e BeginInvoke del controllo attuale, quindi direi che è un pattern rock-solid:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


Ciao,
Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

gvfbb Profilo | Newbie

carissimo per aggiungere elementi al mistero, guarda questi due pezzi di codice dell'evento ricezione dati seriale:

1) è quello suggerito da te, funziona sia in debug che in exe

private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { m_buffer = serialPort.ReadExisting(); this.Invoke((Action)delegate { this.txtSerialText.Text += m_buffer; }); m_buffer = string.Empty; if (!(serialPort.IsOpen)) serialPort.Open(); } catch (Exception ex) { MessageBox.Show(ex.Message, ""); } }


2) uguale al precedente ma dopo il readExisting() ho aggiunto un controllo che quanto letto finisca con il carriage return. Ecco questo funziona in debug ma non in exe:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra


booooooh!

comunque almeno ora tutto funziona correttamente con la soluzione 1)

grazie ancora

Giovanni

gvfbb Profilo | Newbie

correggo il precedente, in effetti nel caso 2) c'era una stupidaggine mia.

Tutto funziona con il seguente codice che include anche il controllo sulla terminazione della stringa:

private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { try { m_buffer += serialPort.ReadExisting(); if (m_buffer.Length >= 2 && m_buffer.Substring(m_buffer.Length-2,2)=="\r\n") { this.Invoke((Action)delegate { this.txtSerialText.Text += m_buffer; }); m_buffer = string.Empty; } if (!(serialPort.IsOpen)) serialPort.Open(); } catch (Exception ex) { MessageBox.Show(ex.Message, ""); } }

0v3rCl0ck Profilo | Guru

ecco bene

per semplificare l'if potresti fare così:

if (m_buffer.EndsWith(Environment.NewLine)) { }


Michael Denny | Visual C# MVP
http://blogs.dotnethell.it/Regulator/
http://dennymichael.wordpress.com
http://mvp.microsoft.com/mvp/Michael%20Denny-5000735
Twitter: @dennymic

gvfbb Profilo | Newbie

eh sì decisamente meglio!

grazie!
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5