studio - uart c#
Memory Leak usando.net SerialPort, ¿hay una mejor manera? (4)
Solo para revivir este problema.
Estoy viendo una pérdida de memoria masiva al usar el evento DataReceived.
Estoy usando un módem USB 3G que proporciona una interfaz de módem en serie. Escribí un pequeño programa que solo abre el puerto serie y se conecta al evento DataReceived. El controlador de eventos es solo un método vacío.
Si quita la memoria del dongle, comenzará a filtrarse a unos 10MB por segundo. No se arroja ninguna excepción.
Girar un nuevo hilo y usar el método de lectura sincrónica (...) resolvió el problema para mí. Ahora recibo una excepción cuando saco el dongle que puedo manejar y no hay pérdidas de memoria.
Tengo un programa que se usa para hablar con hardware a través de rs232. Este software se utiliza para mostrar una secuencia de datos que se envía a través del rs232 desde el hardware tan rápido como sea posible. El problema al que me estoy enfrentando es que con el tiempo la memoria privada asignada al programa explota y se bloqueará muy rápidamente el programa. Si desactivo el hardware de enviar datos durante aproximadamente 2 minutos, entonces el software puede borrar la memoria, pero solo si pause la secuencia de datos.
Estoy usando el evento DataReceived de SerialPort, y parece que este es el lugar donde está el problema, porque provocará un pico de memoria incluso si la función DataReceived no hace nada dentro. Lo único que se me ocurre es que cada vez que se plantea este evento crea un nuevo hilo para ejecutar, y está sucediendo tan rápido que la computadora no tiene tiempo para ejecutar el GC mientras ingresan los datos.
¿Hay alguna manera más eficiente de extraer datos de un objeto SerialPort? Solo me importa una cadena cuando recibo una "NewLine"?
Gracias,
John Vickers
DataReceived se ejecuta en un hilo diferente. Tuve problemas con datos realmente rápidos y este evento me causó problemas. Por eso, creé un hilo y leí los datos yo mismo:
while (this.serialPort.IsOpen)
{
int b = this.serialPort.ReadByte();
if (b != -1)
{
// data is good here
}
}
Pero como dijeron los demás, sin ningún ejemplo de código, no hay mucho con lo que podamos ayudarlo.
Esto es muy inusual, pero técnicamente es posible. SerialPort utiliza subprocesos de subprocesos para llamar al controlador de eventos DataReceived. Tan pronto como reciba uno o más bytes, toma un hilo TP para notificar a su aplicación. Hay un bloqueo en el código de generación de eventos, solo un hilo puede llamar a su controlador de eventos a la vez.
Un posible modo de falla aquí es que una de estas llamadas, probablemente la primera, ingrese un bucle en su código del que nunca sale. Si no ha configurado la propiedad Handshake, el dispositivo puede continuar enviando y activando más llamadas TP, todas ellas bloqueadas en ese bloqueo.
Diagnostica esto desde la ventana Debug + Windows + Threads. Si mi conjetura es precisa, entonces debería ver una gran cantidad de hilos listados aquí. Uno de ellos debe estar dentro de su controlador de eventos DataReceived, haga doble clic en él y observe la pila de llamadas para ver dónde está atrapado. La memoria que está viendo consumida es consumida por las pilas de estos hilos, un megabyte cada uno.
Otra posibilidad es que su código de manejo de eventos DataReceived sea muy lento, posiblemente llamando a Control.Invoke (). Lo suficientemente lento como para no poder seguir el ritmo del dispositivo. Ahora realmente necesita usar la propiedad Handshake para configurar el control de flujo. O arregla lo que sea tan lento. También debería haber una gran cantidad de eventos ErrorReceived por cierto, asegúrese de implementarlos para que pueda ver que esto va mal.
Hay un límite superior en el número de subprocesos TP que se pueden ejecutar al mismo tiempo. Es bastante generoso, 250 veces el número de núcleos. Eso puede consumir fácilmente medio gigabyte de memoria en una máquina típica de doble núcleo.
Desarrollé un lenguaje de programación de puerto en serie controlado por el estado en C # y creo que realmente resuelve casi todos los problemas del puerto serial que todo el mundo encuentra.
¿Podría intentarlo con el siguiente estado simple y verificar fugas de memoria?
state Init
recv();
$len = length($DATA_PACKET);
if("$len > 0") {
log($DATA_PACKET, Debug);
}
end state
Si tiene alguna pregunta, no dude en preguntar.