多线程wpf应用程序中的内存丢失

时间:2018-02-07 11:00:16

标签: c# wpf multithreading out-of-memory

场景如下:具有多个线程的应用程序:2用于请求来自不同源的数据,3用于更新屏幕上的不同信息,1用于按需播放音频。 问题是:应用程序必须不停地工作,并且在启动时工作正常,但过了一会儿(并不总是相同,通常在5到8小时之间),它最终会失败。错误跟踪点 到其中一个绘制线程,我得到异常“System.OutOfMemoryException”5或6分钟,直到最后程序停止。该线程在另外两个内部运行,这两个动画是在更新信息之前和之后持续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;
}

1 个答案:

答案 0 :(得分:2)

您发布的信息不足以帮助解决此问题。内存分析器是您所需要的。我对Redgate ANTS祝你好运。

要注意的一些事项:

  • 您是否使用myEvent + = blah在循环中调用事件。如果是这样,你需要 - =它,否则你会导致内存泄漏。
  • 是否创建了Timer对象?需要注意这些,如果你没有正确取消引用它们就会泄漏。