[英]Memory loss in multi-threaded wpf application
该场景如下所示:具有多个线程的应用程序:2从不同来源请求数据,3更新屏幕上的不同信息,以及1按需播放音频。 问题是:应用程序必须不间断运行,并且启动时可以正常运行,但是过一会儿(通常不一样,通常在5到8个小时之间),它最终会失败。 错误跟踪指向绘画线程之一,在这里我得到了5到6分钟的异常“ System.OutOfMemoryException”,直到程序最终停止。 该线程在其他两个线程中运行,它们是在更新信息之前和之后持续1秒的2个动画(fadeIn,fadeOut)。 如果删除这些动画,程序不会失败(至少24小时)。 我想保留动画,并帮助发现我做错了什么,我想我没有释放资源或类似的东西。
我看两件事:
1)应用程序内存:我已经创建了这个变量
PerformanceCounter ramCounter = new PerformanceCounter("Memory", "Available MBytes");"
在每个线程传递中,我都以这种方式执行它:
"RAM disponible: " + ramCounter.NextValue() + "MB"
该值始终约为3.5 / 4Gb,因此似乎不会丢失内存。
2)线程数:我读到应用程序可以创建的线程数量有限,我认为如果我没有正确关闭线程,那可能就是问题所在。 但这似乎也没有。 我在每次线程传递上执行此操作,它始终为我提供30到35之间的稳定值:
"NumThreads: "+System.Diagnostics.Process.GetCurrentProcess().Threads.Count"
我附上了代码,看看您能否告诉我我做错了什么:
绘制信息的线程(如果我删除动画的行,则应用程序可以正常运行)
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);
}
public void FadeIn()
{
TimeSpan fadeInTime = TimeSpan.Parse("00:00:01");
Double opacityFinalFadeIn = 1d;
Thread.Sleep(750);
this.window.FadeIn(fadeInTime, opacityFinalFadeIn);
}`
实例this.window中的fadeIn函数
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);
}
我应用户@Kelly的要求将有关计时器和事件的此信息放入:
//Timers definition
private System.Windows.Forms.Timer time;
private System.Windows.Forms.Timer wakeup;
//Timers init
this.wakeup = new System.Windows.Forms.Timer();
this.wakeup.Tick += new EventHandler(wakeup_Tick);
this.wakeup.Interval = 30000;
this.time = new System.Windows.Forms.Timer();
this.time.Tick += new EventHandler(time_Tick);
this.time.Interval = 1000;
//Timer functions
private void wakeup_Tick(object sender, EventArgs e){
SetThreadExecutionState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}
private void time_Tick(object sender, EventArgs e){
try{
this.window.setFechaHora(DateTime.Now.ToString("dd / MM / yyyy"), DateTime.Now.ToString("HH:mm"));
}catch (Exception ex){
EscribirLogError("time_Tick " + ex.Message,false);
}
}
//Window function
public void setFechaHora(String fecha, String hora){
this.lblFecha.Content = fecha;
this.lblHora.Content = hora;
}
您发布的信息不足以帮助解决此问题。 您需要一个内存探查器。 我和Redgate ANTS在一起情况很好。
需要注意的几件事:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.