【问题标题】:Memory leak in storyboard under Win8 only?仅在 Win8 下情节提要中的内存泄漏?
【发布时间】:2015-11-11 11:12:19
【问题描述】:

我制作了一个应用程序,其中包含幻灯片。我在 5 台电脑上运行这个应用程序。 3个Win7和2个Win8(都是x64,我的应用是x86)。 在 Win7-PC 上我没有问题。 在 Win8 下,我收到(经过一段不可预测的时间)一些错误消息。 OutOfMemory 异常和 UCEERR_RENDERTHREADFAILURE (HRESULT: 0x88980406)。 微软对此表示:

  1. 如果正在报告 System.OutOfMemoryExceptions,则在性能监视器中监视进程的内存使用情况;特别是所有堆计数器中的 Process\Virtual Bytes、Process\Private Bytes 和 .NET CLR Memory# Bytes。还要在 Windows 任务管理器中监视进程的用户对象和 GDI 对象。如果您可以确定特定资源正在耗尽,则对应用程序进行故障排除以修复导致该资源消耗的任何原因。最终应该会解决 System.OutOfMemoryException。

我不能等待 1 到 5 天,只监视系统并等待错误发生。但也许你们中的某些人可以看到我的代码中的错误?

这是我的 XAML 代码:

    <Window.Resources>
    <Style x:Key="ImgZIndexStyle" TargetType="{x:Type Image}">
        <Setter Property="Panel.ZIndex" Value="2"/>
        <Style.Triggers>
            <Trigger Property="Image.Opacity" Value="1">
                <Setter Property="Panel.ZIndex" Value="3"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Storyboard x:Key="FaderStoryboardHide1Show2">
        <DoubleAnimation Storyboard.TargetName="FirstImage" 
         Storyboard.TargetProperty="Opacity"
         To="0" Duration="0:00:01" />
        <DoubleAnimation Storyboard.TargetName="SecondImage" 
         Storyboard.TargetProperty="Opacity"
         To="1" Duration="0:00:01" />
    </Storyboard>
    <Storyboard x:Key="FaderStoryboardHide2Show1">
        <DoubleAnimation Storyboard.TargetName="SecondImage" 
         Storyboard.TargetProperty="Opacity"
         To="0" Duration="0:00:01" />
        <DoubleAnimation Storyboard.TargetName="FirstImage" 
         Storyboard.TargetProperty="Opacity"
         To="1" Duration="0:00:01" />
    </Storyboard>
</Window.Resources>
<Grid>
    <Grid Name="SlideShowGrid" ZIndex="0">
        <Button Name="SlideShowButton" Click="SlideShowButton_OnClick">
            <Grid>
                <Image x:Name="FirstImage" Stretch="UniformToFill" Style="{StaticResource ImgZIndexStyle}" Opacity="1" />
                <Image x:Name="SecondImage" Stretch="UniformToFill" Style="{StaticResource ImgZIndexStyle}" Opacity="0" />
            </Grid>
        </Button>
    </Grid>
</Grid>

还有我的班级:

private void SlideShowTimer_Tick(object sender, EventArgs e)
{
    Image newImage;
    Storyboard tempStoryboard;
    if (FirstImage.Opacity == 1)
    {
        tempStoryboard = (Storyboard)FindResource("FaderStoryboardHide1Show2");
        newImage = SecondImage;
    }
    else
    {
        tempStoryboard = (Storyboard)FindResource("FaderStoryboardHide2Show1");
        newImage = FirstImage;
    }
    if (_imageCounter >= _fileList.Count - 1)
        _imageCounter = 0;
    else
        _imageCounter++;
    newImage.Source = new BitmapImage(new Uri(_fileList[_imageCounter]));
    tempStoryboard.Begin();
}

【问题讨论】:

  • 看来您需要在分配新图像之前处理您以前的图像newImage.Source
  • 但是我只设置了一个新的源,并没有创建一个新的图像对象。还是我误解了什么? “newImage = SecondImage”不就是对SecondImage的引用吗?
  • newImage.Source=img1; newImage.Source=img2; 现在你失去了对img1 的引用而没有释放它的资源......
  • 我建议使用内存分析器,即使您必须让它运行并记录 4 或 5 个小时并且您没有收到错误,它仍然应该向您显示内存泄漏的位置是。
  • @RonBeyer:是的,但是错误只发生在 Win8 上,而我的 VS 在 Win7 上。我不知道如何在没有 VS 的情况下使用内存分析器。

标签: c# .net wpf memory-management memory-leaks


【解决方案1】:

垃圾收集器使用启发式算法来优化某些操作。因此,您不能期望在不同 PC 中的内存问题有一致的行为。

不要让您的一次性物品在未处理的情况下超出范围。您应该在创建新实例之前处置现有图像。

if (newImage != null)
    newImage.Dispose();

newImage.Source = new BitmapImage(new Uri(_fileList[_imageCounter]));

编辑

Bitmap 类是Image 类的实现。 Image 类是一个抽象类。所以,请使用一次性的 Bitmap 而不是 Image。

Bitmap newImage;
....
mewImage.Dispose();

【讨论】:

  • Image 默认没有 Dispose 方法。我看不到如何在这里使用“使用{}”并且自己实现它似乎非常复杂。有人有像图像这样的对象的简单示例吗?
  • 好的,让我们看看我是否有任何错误的想法,或者您是否没有理解我的意思。我有 2 个图像对象,每个对象都有一个 Source,每次调用该方法时都会创建一个“新 BitmapImage”。在方法结束时,BitmapImage 被放入 Image.Source。下次我调用该方法时,我必须在创建新的之前处理 BitmapImage。所以我应该要Dispose Image的Source,也就是到这个时候,一个ImageSource-object。但这不是那么容易处理的。但是从 ImageSource 创建一个新的 BitmapImage 根本没有帮助,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
  • 2015-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多