Foros del Web » Programación para mayores de 30 ;) » .NET »

[SOLUCIONADO] Pérdida de memoria en aplicación multihilo

Estas en el tema de Pérdida de memoria en aplicación multihilo en el foro de .NET en Foros del Web. El escenario es el siguiente: una aplicación con varios hilos: 2 para pedir datos a diferentes fuentes, 3 para actualizar diferentes informaciones en pantalla, y ...
  #1 (permalink)  
Antiguo 07/02/2018, 01:13
 
Fecha de Ingreso: diciembre-2012
Mensajes: 17
Antigüedad: 5 años, 4 meses
Puntos: 2
Pérdida de memoria en aplicación multihilo

El escenario es el siguiente: una aplicación con varios hilos: 2 para pedir datos a diferentes fuentes, 3 para actualizar diferentes informaciones en pantalla, y 1 para reproducir audios a demanda.
El problema: la aplicación tiene que funcionar non-stop, y al arrancar funciona bien, pero al cabo de un tiempo (no siempre el mismo, suelen ser entre 5 y 8 horas) acaba fallando. La traza de error apunta
a uno de los hilos de pintado, en donde me salta la excepción "System.OutOfMemoryException" durante 5 o 6 minutos, hasta que al final el programa se para. Ese thread ejecuta dentro otros dos, que son
2 animaciones (fadeIn,fadeOut) que duran 1seg, antes y después de actualizar la información. Si quito esas animaciones el programa no falla (almenos durante 24h). Me gustaría mantener las animaciones, y que memoria
ayudarais a detectar qué estoy haciendo mal, supongo que no estoy liberando recursos o algo parecido.

Por mi parte he mirado dos cosas:
1) Memoria de la aplicación: he creado esta variable
Código:
PerformanceCounter ramCounter = new PerformanceCounter("Memory", "Available MBytes");"
y en cada pasada del thread lo ejecuto mediante
Código:
"RAM disponible: " + ramCounter.NextValue() + "MB"
El valor está siempre en torno a 3.5/4Gb, así que no parece estar perdiendo memoria.
2) Número de threads: leí que hay un límite de threads que una aplicación puede crear, y pensé que si no los estaba cerrando adecuadamente quizá ese fuera el problema. Pero no parece tampoco. Ejecuto esto en cada pasada y me da siempre un valor estable de entre 30 y 35:
Código:
"NumThreads: "+System.Diagnostics.Process.GetCurrentProcess().Threads.Count"

Adjunto el código, y a ver si me podéis decir qué estoy haciendo mal:

Thread que pinta información (si quito las líneas de las animaciones; la aplicación funciona ok)
Código:
while (true){
    try{
        EscribirLogError("PintarTiempos - RAM disponible: " + ramCounter.NextValue() + "MB",false);
        tiempoPrevisiones = int.Parse(ConfigurationManager.AppSettings["TIEMPOPREVS"]);

		//Animación quitar tiempos
		tFadeOut = new Thread(new ThreadStart(FadeOut));
		tFadeOut.SetApartmentState(ApartmentState.STA);
		tFadeOut.Start();
		//Pintar tiempos
		this.window.pintaTiempos(previsiones);
		Console.WriteLine("NumThreads: " + System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
		EscribirLogError("NumThreads: "+System.Diagnostics.Process.GetCurrentProcess().Threads.Count,false);
		//Animación tiempos nuevos
		tFadeIn = new Thread(new ThreadStart(FadeIn));
		tFadeIn.SetApartmentState(ApartmentState.STA);
		tFadeIn.Start();
                        
		Thread.Sleep(tiempoPrevisiones * 1000);
                    
    }catch(Exception e){
        EscribirLogError("PintaTiempos:" + e.Message, true);
	}
}
Código:
public void FadeIn()
        {
            TimeSpan fadeInTime = TimeSpan.Parse("00:00:01");
            Double opacityFinalFadeIn = 1d;
            Thread.Sleep(750);
            this.window.FadeIn(fadeInTime, opacityFinalFadeIn);
        }
La función fadeIn de la instancia this.window
Código:
public void FadeIn(TimeSpan fadeInTime, Double d)
{
	this.Dispatcher.Invoke(new System.Action(() =>
	{
		try
		{
			var fadeInAnimation = new DoubleAnimation(1d, fadeInTime);
			for (int i = 0; i < this.lblTiempos.Length; i++)
			{
				this.lblLineas[i].BeginAnimation(Label.OpacityProperty, fadeInAnimation);
				this.lblDestinos[i].BeginAnimation(Label.OpacityProperty, fadeInAnimation);
				this.lblTiempos[i].BeginAnimation(Label.OpacityProperty, fadeInAnimation);
			}
		}
		catch (Exception e)
		{
			this.programa.EscribirLogError("FadeIn.Dispatcher:" + e.Message, true);
		}
	}), null);
}
  #2 (permalink)  
Antiguo 09/02/2018, 01:17
 
Fecha de Ingreso: diciembre-2012
Mensajes: 17
Antigüedad: 5 años, 4 meses
Puntos: 2
Respuesta: Pérdida de memoria en aplicación multihilo

Arreglado. He cambiado la manera de invocar a las funciones de animación FadeIn/FadeOut. En lugar de crear nuevos threads para que se ejecuten las invoco como funciones normales, y han dejado de saltar las excepciones.

Debo tener algún problema de memoria que no gestiono adecuadamente, y desconozco cuál es, pero por lo menos funciona, y la verdad es que el comportamiento de cara a la UI, en este caso es prácticamente idéntico, por lo que la solución me es válida.

Me gustaría saber dónde está el error, porque creo que debería funcionar igual de bien creando un thread nuevo para cada animación, pero mientras no descubro el fallo, por lo menos si alguien está en la misma situación, a ver si esta solución parcial le sirve para salir del paso.



La zona horaria es GMT -6. Ahora son las 01:38.