Tengo un programa de winform que hace un IO asincrónico en un SerialPort
. Sin embargo, periódicamente encuentro un problema con el congelamiento del programa en la llamada SerialPort.Close(), aparentemente al azar.C# Winform freezing en SerialPort.Close
Creo que es un problema de seguridad de subprocesos, pero no estoy seguro de cómo solucionarlo si lo es. Traté de agregar/eliminar el controlador asincrónico DataReceived con las funciones de apertura/cierre del puerto y descartar los búferes de entrada y salida en el puerto, pero parece que no hace nada. Creo que el código importante SerialPort
es el siguiente:
using System;
using System.Collections.Generic;
using System.IO.Ports;
public class SerialComm
{
private object locker = new object();
private SerialPort port;
private List<byte> receivedBytes;
public SerialComm(string portName)
{
port = new SerialPort(portName);
port.BaudRate = 57600;
port.Parity = Parity.None;
port.DataBits = 8;
port.StopBits = StopBits.One;
receivedBytes = new List<byte>();
}
public void OpenPort()
{
if(port!=null && !port.IsOpen){
lock(locker){
receivedBytes.Clear();
}
port.DataReceived += port_DataReceived;
port.Open();
}
}
public void ClosePort()
{
if(port!=null && port.IsOpen){
port.DataReceived -= port_DataReceived;
while(!(port.BytesToRead==0 && port.BytesToWrite==0)){
port.DiscardInBuffer();
port.DiscardOutBuffer();
}
port.Close();
}
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try{
byte[] buffer = new byte[port.BytesToRead];
int rcvdBytes = port.Read(buffer, 0, buffer.Length);
lock(locker){
receivedBytes.AddRange(buffer);
}
//Do the more interesting handling of the receivedBytes list here.
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.ToString());
//put other, more interesting error handling here.
}
}
}
ACTUALIZACIÓN
Gracias a @ respuesta de Afrin señalando la condición de punto muerto con el hilo de interfaz de usuario (This blog post hace un buen trabajo de describir, y da varios otros buenos consejos), hice un cambio simple y todavía no he podido reproducir el error.
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try{
byte[] buffer = new byte[port.BytesToRead];
int rcvdBytes = port.Read(buffer, 0, buffer.Length);
lock(locker){
receivedBytes.AddRange(buffer);
}
ThreadPool.QueueUserWorkItem(handleReceivedBytes);
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.ToString());
//put other, more interesting error handling here.
}
}
private void handleReceivedBytes(object state)
{
//Do the more interesting handling of the receivedBytes list here.
}
Para asegurarse de que he entendido bien, en resumen, hay un estancamiento en el '' SerialPort' entre el Read' y la 'Cerrar' llamadas? – chezy525
tiene que cambiar la forma en que invoca las actualizaciones del elemento de la interfaz de usuario en el controlador de eventos port_DataReceived, use BeginInvoke para actualizar en lugar de Invoke, o como se describe en la solución, use otro hilo para manejar el evento. – Afshin
El manejo de los datos para la interfaz de usuario en un hilo diferente parece haber resuelto el problema. ¡Gracias! – chezy525