繁体   English   中英

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

[英]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在一起情况很好。

需要注意的几件事:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM