visual studio serialport serial received example event data application c# multithreading visual-studio-2010 event-handling serial-port

c# - serialport - visual studio system io ports



Invocando con textbox c# (2)

Parte de mi programa utiliza un controlador de eventos para los datos de recepción de mi puerto serie. La idea es cuando se reciben datos de que el texto recibido se agrega al cuadro de texto (rx). No solía tener este problema, pero algo ha cambiado y no puedo entender qué. Así que ahora estoy reexaminando la forma en que se maneja esto.

Durante la carga de formulario de mi winform, lo último que hago es

if (!serialPort1.IsOpen) { serialPort1.Open(); serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); }

Luego tengo el controlador de eventos

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { string indata1 = serialPort1.ReadExisting(); // rx.Text = " "; accidentally posted this. it was from trial and error. rx.AppendText(Environment.NewLine + indata1); }

Cuando ejecuto el programa, se detiene en rx.AppendText(Environment.NewLine + indata1); y da el error

invalidoperationexception no se ha manejado: Control "se accede desde un hilo que no sea el hilo en el que se creó.

De lo que he podido leer sugiere que necesito usar BeginInvoke o BeginInvoke .

Nunca he tenido problemas para anexar el texto, así que ahora no puedo entender por qué es un problema. También de lo que he estado leyendo al invocar simplemente no lo entiendo.

¿Alguien puede ayudarme a entender cómo usar la instancia de invocación para mi situación? o tal vez mostrarme otra forma de anexar el cuadro de texto?


Las actualizaciones en las aplicaciones GUI solo deben hacerse en el hilo de la GUI. Otro hilo que intenta actualizar los componentes de la GUI directamente dará como resultado el error que describió o un comportamiento aparentemente aleatorio.

La función de Invoke & friends es habilitar un subproceso secundario para reenviar de forma segura las actualizaciones de GUI al subproceso de GUI, que luego las procesará desde una cola.

En su caso (asumiendo WinForms aquí):

rx.BeginInvoke( (Action)(() => { rx.AppendText(Environment.NewLine + indata1); }));

BeginInvoke es asíncrono, por lo que el hilo que lo llama no esperará a que las actualizaciones reales se procesen antes de continuar, mientras Invoke es síncrono.


Por lo general, la excepción que está viendo ocurre cuando se ejecuta en modo de depuración, y si ejecuta su aplicación en modo de lanzamiento, es poco probable que vea la excepción.

Sin embargo, es mejor utilizar invocar, como lo ha leído. Algo como esto:

private delegate void RefreshTextBox(); private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { //this event is raised in an event separate from UI thread, //so InvokeRequired must be checked and Invoke called to update UI controls. if (this.InvokeRequired) { RefreshTextBox d = new RefreshTextBox(RefreshTextBoxResults); Invoke(d); } else { RefreshTextBoxResults(); } } private void RefreshTextBoxResults() { string indata1 = serialPort1.ReadExisting(); rx.Text = " "; rx.AppendText(Environment.NewLine + indata1); }

La primera vez que veas esto invocar, es casi imposible de seguir, pero échale un vistazo y dale tiempo y tendrá sentido. Promesa. :)