c# - studio - SerialPort.Read(...) no respeta ReadTimeOut
uart c# (1)
quizás agregar una prueba en los ''bytes para leer'' del puerto puede ayudar a evitar los controladores mal codificados:
length = (_serialPort.BytesToRead > 0) ? _serialPort.Read(buffer, 0, 512) : 0;
mejor aún, use
_serialPort.DiscardInBuffer();
¡en lugar!
Tengo un error en algún código heredado que se comunica con un terminal de pago.
Justo antes de que se inicie un nuevo pago, el código intenta borrar el buffer interno de lectura de SerialPort.
Recorté el código al mínimo. Utiliza el tipo .NET SerialPort. Se establece un tiempo de espera de lectura de 50 ms. Luego lee 512 bytes y continúa haciéndolo hasta que no se lean más bytes o hasta que se genere TimeoutException.
Agregamos un montón de registros y mostró que la llamada al primer método de Lectura (...) a veces toma de 10 a 15 minutos, incluso con un tiempo de espera de 50 ms. Luego se lanza una TimeoutException y la aplicación continúa. Pero durante la lectura (...) la aplicación se bloquea.
Esto no siempre ocurre, las máquinas con Windows 2000 parecen ser más propensas a este error por alguna razón.
public class Terminal
{
private SerialPort _serialPort = new SerialPort();
public void ClearReadBuffer()
{
try
{
_serialPort.ReadTimeout = 50;
int length;
do
{
var buffer = new byte[512];
length = _serialPort.Read(buffer, 0, 512);
} while (length > 0);
}
catch (TimeoutException) {}
}
}
Cualquier ayuda es apreciada.
PD: la mayoría de los informes de error provienen de máquinas W2K donde el dispositivo está conectado a un puerto EdgePort, que simula un grupo de puertos COM virtuales. Su controlador crea un grupo (8 o más) de puerto COM local.
Pero también tenemos informes de Windows 7. También podemos reproducir el problema si conectamos directamente el dispositivo a la PC (no EdgePort). Sin embargo, no tan a menudo y cuando ocurre, la demora no es de 10 minutos, sino más bien de 1 a 2 minutos.
Actualización : Intenté muchas cosas para arreglar esto. Fue difícil de reproducir, pero se produjo con bastante frecuencia en el campo porque allí se distribuye en miles de PC. En realidad reemplazó el tipo .NET 2.0 SerialPort con otra versión de código abierto. Funcionó sin problemas en una PC donde podíamos reproducirla como 60 - 70% de las veces. Pero, por desgracia, durante una prueba piloto en producción, los problemas aún continuaban ocurriendo.
El código para la terminal de pago se escribió un par de años antes y lo porté a otra aplicación. Durante el puerto volví a factorizar algún código, pero mantuve la funcionalidad original. Al comunicarse con la terminal, el código:
- Disparar otro hilo del grupo de subprocesos
- Envía el mensaje al dispositivo
- Leyó desde el puerto serie hasta que se recibió una respuesta o se produjo un tiempo de espera.
Mientras tanto, el hilo principal tenía un ciclo while que contenía un Thread.Sleep (50) y una llamada a Application.DoEvents () (yuck!). Refactoré todo este "ciclo de espera" e hice uso de un WaitHandle (AutoResetEvent / ManualResetEvent). Solo esperé hasta que se estableció este mango. Funcionó sin problemas, pero en ciertas PC, todas las comunicaciones del puerto serie se congelaron durante unos minutos hasta que algo lo activó. Volví a habilitar la forma de trabajar de Application.DoEvents () y los problemas desaparecieron.
Desafortunadamente todavía está ahí, un enigma para mí por qué se requiere aquí y por qué causa efectos secundarios tan graves. Las aplicaciones son compatibles con otros 5 tipos de dispositivos de puerto en serie. La comunicación con estos dispositivos nunca requirió algo como esto.