【问题标题】:Process Memory increase WPF application进程内存增加 WPF 应用程序
【发布时间】:2020-12-25 18:35:55
【问题描述】:

我正在创建一个 WPF 程序,用于使用 Syncfusion 库编辑 PowerPoint 演示文稿,但每当我运行该程序时,我都会看到从一个页面导航到另一个页面时内存增加。我正在使用带有在多个页面之间导航的窗口的 WPF 应用程序。

这个问题究竟是怎么遇到的?

谢谢。

这些照片显示了泄漏的位置:

PS:请关注 home.cs 中的 InitializeNonUITasks 方法,因为这是泄漏的地方。

主页 XAML:

<Page x:Class="ProjectSABX.Pages.Home"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:local="clr-namespace:ProjectSABX.Pages"
  xmlns:syncfusion="clr-namespace:Syncfusion.Windows;assembly=Syncfusion.Shared.Wpf"
  xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
  mc:Ignorable="d"
  Width="1175" Height="660" KeyDown="Window_KeyDown"
  Title="Home">
<Grid ShowGridLines="False" Margin="2,-2,-2,2">
    <Grid Grid.Row="0" ShowGridLines="False">
        <Grid.Background>
            <SolidColorBrush Color="White" Opacity="0.5" />
        </Grid.Background>
        <Grid.RowDefinitions>
            <RowDefinition Height="2.5*"></RowDefinition>
        </Grid.RowDefinitions>
        <Rectangle Height="52" Grid.Row="0"  VerticalAlignment="Top" Fill="#FF80A20D"></Rectangle>
        <TextBlock Name="titleBarTextBlock" Text="Aperçu" Height="40" Foreground="White" FontFamily="Segoe UI" FontWeight="Normal" Padding="15" FontSize="17.75"  VerticalAlignment="Top" Grid.Row="0"  HorizontalAlignment="Center"></TextBlock>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 15 10 0" Grid.Column="3" Grid.Row="0">
        </StackPanel>
        <Image Source="/Images/ViewerIcons/ppt__logo for header.png" Grid.Column="0" HorizontalAlignment="Left" Margin="15" VerticalAlignment="Top" Height="30"></Image>
    </Grid>

    <Grid Grid.Row="1" ShowGridLines="False">
        <Grid.RowDefinitions>
            <RowDefinition Height="0*" />
            <RowDefinition Height="445*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="59*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="8*" />
        </Grid.ColumnDefinitions>
        <Border ClipToBounds="True" BorderBrush="Black" BorderThickness=".7" Grid.Row="1" Grid.Column="0" Grid.RowSpan ="3" Margin="0,51,3,0">
            <ScrollViewer Name="scrollViewer" Focusable="False" CanContentScroll="False" BorderBrush="Black" BorderThickness="1" HorizontalScrollBarVisibility="Auto" Grid.Row="1" Grid.Column="0" Grid.RowSpan ="3">
                <Grid ShowGridLines="False">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*" />
                        <ColumnDefinition Width="9*" />
                    </Grid.ColumnDefinitions>
                    <StackPanel Name="stackpanel" Grid.Column="1" Width="170" />
                </Grid>
            </ScrollViewer>
        </Border>

        <Image Name ="centerSlideImage" Grid.Row="1" Grid.Column="1" Margin="0,57,5,19" />

        <Canvas Name="loadingIndicatorCanvas" Visibility="Collapsed" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" Margin="-250,-100,0,0">
            <Canvas Canvas.Left="21.75" Canvas.Top="14" Height="81.302" Width="80.197">
                <Canvas.Resources>
                    <Style TargetType="Ellipse">
                        <Setter Property="Width" Value="5" />
                        <Setter Property="Height" Value="5" />
                        <Setter Property="Fill" Value="#FF9BD226" />
                    </Style>
                </Canvas.Resources>

                <Ellipse x:Name="_00" Canvas.Left="24.75" Canvas.Top="50" />
                <Ellipse x:Name="_01" Canvas.Top="36" Canvas.Left="29.5" />
                <Ellipse x:Name="_02" Canvas.Left="43.5" Canvas.Top="29.75" />
                <Ellipse x:Name="_03" Canvas.Left="57.75" Canvas.Top="35.75" />
                <Ellipse x:Name="_04" Canvas.Left="63.5" Canvas.Top="49.75" />
                <Ellipse x:Name="_05" Canvas.Left="57.75" Canvas.Top="63.5" />
                <Ellipse x:Name="_06" Canvas.Left="43.75" Canvas.Top="68.75" />
                <Ellipse x:Name="_07" Canvas.Top="63.25" Canvas.Left="30" />
                <Ellipse Stroke="{x:Null}" Width="39.5" Height="39.5" Canvas.Left="31.75" Canvas.Top="37" Fill="{x:Null}" />
            </Canvas>
        </Canvas>

        <Grid Grid.Row="3" Grid.Column="1" ShowGridLines="False" Margin="0, -10">
            <Grid.RowDefinitions>
                <RowDefinition Height="0.5*" />
                <RowDefinition Height="20*" />
                <RowDefinition Height="10*" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="42*" />
                <ColumnDefinition Width="45*" />
                <ColumnDefinition Width="44*" />
                <ColumnDefinition Width="45*" />
                <ColumnDefinition Width="238*" />
                <ColumnDefinition Width="30*" />
                <ColumnDefinition Width="40*" />
                <ColumnDefinition Width="46*" />
                <ColumnDefinition Width="30*" />
                <ColumnDefinition Width="45*" />
            </Grid.ColumnDefinitions>
            <Image Name="openDocument" Grid.Row="1" Grid.Column="1" Height="30" Width="30" Source="/Images/ViewerIcons/ppt__open.png" MouseDown="openDocument_MouseDown" MouseEnter="openDocument_MouseEnter" MouseLeave="openDocument_MouseLeave" Margin="0,5,7,4"></Image>
            <Image Name="createPdfDocument" Grid.Row="1" Grid.Column="3" Height="30" Width="30" Source="/Images/ViewerIcons/ppt_pdf.png" MouseDown="createPdfDocument_MouseDown" MouseEnter="createPdfDocument_MouseEnter" MouseLeave="createPdfDocument_MouseLeave" Margin="0,5,8,4"></Image>
            <DockPanel Grid.Row="1" Grid.Column="6" Grid.ColumnSpan="3">
                <Image Name="prevDocument"  Height="30" Width="30" Source="/Images/ViewerIcons/ppt__back.png" MouseDown="prevDocument_MouseDown" MouseEnter="prevDocument_MouseEnter" MouseLeave="prevDocument_MouseLeave"></Image>
                <Label Name="lblPageDisplay" Height="30" MinWidth="30" FontFamily="Segoe UI" FontWeight="Bold" FontSize="18" VerticalAlignment="Center" VerticalContentAlignment="Center" Padding="35,0,0,0" Foreground="#646464" />
                <Image Name="NextDocumentIconImage" Height="30" Width="30" Source="/Images/ViewerIcons/ppt__for.png"  MouseDown="NextDocument_MouseDown" MouseEnter="NextDocument_MouseEnter" MouseLeave="NextDocument_MouseLeave" Margin="-10,0"></Image>
            </DockPanel>
        </Grid>
    </Grid>
</Grid>

主页 C#:

    public Home()
    {
        InitializeComponent();

        pdfBackroundWorker.DoWork += pdfBackroundWorker_DoWork;
        pdfBackroundWorker.RunWorkerCompleted += pdfBackroundWorker_RunWorkerCompleted;
        this.Background = new SolidColorBrush(Color.FromRgb(244, 244, 244));
        filePath = "/Data/Template.pptx";
        
        InitializeNonUITasks();
        InitializeUITasks(filePath);
        

    }

        
    private void openDocument_MouseDown(object sender, MouseButtonEventArgs e)
    {
        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
        dlg.Filter = "PowerPoint Presentations|*.pptx";
        Nullable<bool> result = dlg.ShowDialog();
        if (result == true)
        {
            string filename = dlg.FileName;
            filePath = filename;
            slideNumber = 1;
            displayBackroundWorker.RunWorkerAsync();
        }
    }
    private void InitializeNonUITasks()
    {
        try
        {
            presentation = Presentation.Open(filePath);
        }
        catch (Exception exp)
        {
            MessageBox.Show("This PowerPoint Presentation cannot be opened properly, please contact support");
            return;
        }
        slideImageSources.Clear();
        thumbnailImageSource.Clear();
        printImages.Clear();
        currentSlideNumber = 0;
        presentation.ChartToImageConverter = new ChartToImageConverter();
        presentation.ChartToImageConverter.ScalingMode = Syncfusion.OfficeChart.ScalingMode.Best;
        try
        {
            foreach (ISlide slide in presentation.Slides)
            {
                using (System.Drawing.Image image = slide.ConvertToImage(Syncfusion.Drawing.ImageType.Bitmap))
                {
                    System.Drawing.Image.GetThumbnailImageAbort myCallback = new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback);
                    printImages.Add(image.Clone() as System.Drawing.Image);
                    System.Drawing.Image newImage = image.GetThumbnailImage(170, 100, myCallback, System.IntPtr.Zero);
                    using (Stream ms = new MemoryStream())
                    {
                        newImage.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                        var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
                        thumbnailImageSource.Add(decoder.Frames[0]);
                    }

                    using (Stream ms = new MemoryStream())
                    {
                        image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                        var decoder = BitmapDecoder.Create(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
                        slideImageSources.Add(decoder.Frames[0]);
                    }
                }
            }
        }
        catch (Exception)
        {
            MessageBox.Show("This PowerPoint Presentation cannot be converted to images properly, please contact support");
            return;
        }
    }

主窗口 XAML:

<Frame Grid.Column="1" Grid.Row="1" NavigationUIVisibility="Hidden" x:Name="Main" Source="./Pages/Home.xaml">
        <Frame.Background>
            <SolidColorBrush Color="#FFB0B0B0" Opacity="0.49" />
        </Frame.Background>
    </Frame>

MainWindow.cs:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        DataContext = this;
        InitializeComponent();
    }
    private void ButtonClickHomePage(object sender, RoutedEventArgs e)
    {
        Main.Content = new Home();
    }
 }

Edit1:我尝试对每个实现了 IDisposable 的对象使用 dispose() 方法,起初导航时,内存进程减少。然后当我从一个页面导航到另一个页面时,它会再次增加。

【问题讨论】:

  • 能否请您进一步详细说明,我没听清楚。
  • 根据内存配置文件可能是 MemoryStream 对象,但不确定如何/为什么会发生这种情况。它实现了IDisposable 接口并在using 语句中使用,因此应该在此之后处理它。快照仍然显示内存使用率较低(例如内存流为 13MB),您可以共享稍后的快照吗?
  • @asaf92 我添加了快照,包括我启动应用程序的那一刻,首先在主页和其他页面之间导航,然后返回主页并再次重新导航多次
  • 由于快照信息,即使是最大的内存消耗者也会消耗相当多的兆字节。您的分析器是否在“进程内存 (GB)”图表上显示托管或总内存消耗?所以一般建议是 - 找到占用千兆字节 RAM 的对象,并查看它们为什么会保存在内存中,是否应该保存。

标签: c# .net wpf memory syncfusion


【解决方案1】:

我们无法使用给定的代码示例最终重现上述问题。供您参考,我们附上了我们尝试重现上述问题的示例。

示例链接 https://www.syncfusion.com/downloads/support/directtrac/general/ze/PresentationSample-1588894092

在此示例中,最大内存使用量大约小于 500MB。因此,请向我们提供上述修改后的示例以重现上述问题,以便我们进一步分析并为您提供适当的详细信息。

【讨论】:

    【解决方案2】:

    这样很难确定问题,但我确实有一些建议:

    通常是在所有实现IDisposable接口的对象上调用Dispose

    • 检查IDisposable 接口的所有对象并调用Dispose()(如果可用)。例如:newImage.Dispose()(或使用using
    • 此外,printImagesthumbnailImageSource 等列表中的所有一次性对象也应进行处理。
    • 另外,我认为decoderpresentation 也应该被处理掉,尽管我可能弄错了。

    这将为您提供一个很好的起点 - 可能还有更多,但您应该先排除并解决此问题。

    很可能是循环导致内存增加。

    这里有更多关于IDisposable 的信息。此外,如果您自己实现了IDisposable 接口 - 也很容易犯错误。在这种情况下,您应该仔细检查。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 2013-10-14
      • 1970-01-01
      • 2012-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多