简体   繁体   English

如何在 UWP 应用程序中打印 pdf 文件后减少内存消耗

[英]How to reduce memory consumption after printing a pdf file in UWP app

I'm using Microsoft's PrintHelper(Microsoft.Toolkit.Uwp.Helpers.PrintHelper) to print the pdf for my app.我正在使用 Microsoft 的 PrintHelper(Microsoft.Toolkit.Uwp.Helpers.PrintHelper) 为我的应用程序打印 pdf。 Now printing actually works by rendering the pdf into a BitmapImage and thereby printing the BitmapImage .现在打印实际上是通过将 pdf 渲染到BitmapImage中从而打印BitmapImage来工作的。 This works fine for small number of pages.这适用于少量页面。 But when the number of pages increases, the memory consumption for rendering the BitmapImages goes high.但是当页面数量增加时,用于渲染 BitmapImages 的内存消耗会增加。 Although I use garbage collection the memory is not released after the print operation.虽然我使用垃圾收集,但打印操作后内存不会释放。 When the printing is performed a quite more number of times, the app gets crashed.当打印执行的次数更多时,应用程序会崩溃。

Is there any way to reduce this memory leak or to make the printing efficient?有什么方法可以减少这种内存泄漏或提高打印效率吗?

Here is my code:这是我的代码:

In this, the function GetImages() returns the BitmapImages.在此,函数GetImages()返回 BitmapImages。 PrintPreview is the grid where the BitmapImages are displayed. PrintPreview是显示位图图像的网格。

    public async Task PrintAsync()
    {
        GC.Collect();
        foreach (var image in await GetImages())
        {
            Grid grid = new Grid();
            var printpreview = new PrintPreview(image);
            grid.Children.Add(printpreview);

            printHelper.AddFrameworkElementToPrint(grid); printpreview = null;
            grid = null;
            GC.Collect();
        }
    }

Even though I force collect GC after the printing operation, the memory is not released.即使我在打印操作后强制收集 GC,内存也没有释放。

    private void PrintHelper_OnPrintSucceeded()
    {
        GC.Collect();
        printHelper.ClearListOfPrintableFrameworkElements();
        printHelper.Dispose();
        GC.SuppressFinalize(this);

    }

Edit:编辑:

Below is the GetImages() function.下面是 GetImages() 函数。

    public async Task<IEnumerable<ImageSource>> GetImages(int qualityRatio = 2)
    {
        GC.Collect();
        if (pdf_stream != null)
        {
            StorageFolder myfolder = ApplicationData.Current.LocalFolder;
            StorageFile pdf_file;
            pdf_file = await myfolder.CreateFileAsync(filename + ".pdf", CreationCollisionOption.GenerateUniqueName);
            using (Stream outputStream = await pdf_file.OpenStreamForWriteAsync())
            {
                await pdf_stream.AsStreamForRead().CopyToAsync(outputStream);
            }
            var result = new List<ImageSource>();
            try
            {
                var document = await PdfDocument.LoadFromFileAsync(pdf_file);
                for (uint i = 0; i < document.PageCount; i++)
                {
                    using (var page = document.GetPage(i))
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            using (var randomStream = memoryStream.AsRandomAccessStream())
                            {
                                var image = new BitmapImage();
                                var options = new PdfPageRenderOptions
                                {
                                    DestinationWidth = (uint)page.Size.Width * (uint)qualityRatio,
                                    DestinationHeight = (uint)page.Size.Height * (uint)qualityRatio
                                };
                                await page.RenderToStreamAsync(randomStream, options);
                                image.SetSource(randomStream);
                                result.Add(image);
                            }
                        }
                    }
                }
            }
            catch { }
            return result;
        }
        return null;
    }

PrintPreview.xaml打印预览.xaml

<Page
x:Class="App.src.PrintPreview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
    <Image Source="{Binding}"   Stretch="Uniform" Margin="0"></Image>
</Grid>

PrintPreview.xaml.cs打印预览.xaml.cs

public sealed partial class PrintPreview : Page
{
    public PrintPreview(ImageSource image)
    {
        this.InitializeComponent();
        this.DataContext = image;
    }
}

By testing, you can extra create a Image control, first pass BitmapImage to Image.Source, and then use randomStream to set Source, it will save some memory.通过测试,可以额外创建一个Image控件,先将BitmapImage传给Image.Source,然后使用randomStream设置Source,会节省一些内存。

MainPage.xaml:主页.xaml:

<Image x:Name="Output" Visibility="Collapsed" ></Image>

MainPage.cs:主页.cs:

using (var page = document.GetPage(i))
{
    var stream = new InMemoryRandomAccessStream();
    await page.RenderToStreamAsync(stream);
    BitmapImage src = new BitmapImage();
    Output.Source = src; // pass bitmapImage to Source
    await src.SetSourceAsync(stream);
    stream.Dispose();
    result.Add(src);
}

In addition, I found using urisource will save more memory compared to using stream to load bitmapImages.此外,我发现与使用流加载位图图像相比,使用urisource会节省更多内存。 But you need to convert every page from pdf to StorageFile and save it in temp folder, then use UriSource to convert it to bitmapImage.但是您需要将每个页面从 pdf 转换为 StorageFile 并将其保存在临时文件夹中,然后使用 UriSource 将其转换为 bitmapImage。 It is more complicated, but you can also try it to check.它比较复杂,但你也可以尝试检查一下。

I'm using Microsoft's PrintHelper(Microsoft.Toolkit.Uwp.Helpers.PrintHelper) to print the pdf for my app.我正在使用 Microsoft 的 PrintHelper(Microsoft.Toolkit.Uwp.Helpers.PrintHelper) 为我的应用程序打印 pdf。 Now printing actually works by rendering the pdf into a BitmapImage and thereby printing the BitmapImage .现在打印实际上是通过将 pdf 渲染为BitmapImage并因此打印BitmapImage来工作的。 This works fine for small number of pages.这适用于少量页面。 But when the number of pages increases, the memory consumption for rendering the BitmapImages goes high.但是当页数增加时,用于渲染 BitmapImages 的 memory 消耗会变高。 Although I use garbage collection the memory is not released after the print operation.虽然我使用垃圾回收,但 memory 在打印操作后不会释放。 When the printing is performed a quite more number of times, the app gets crashed.当打印执行的次数相当多时,应用程序就会崩溃。

Is there any way to reduce this memory leak or to make the printing efficient?有什么办法可以减少这种 memory 泄漏或提高打印效率?

Here is my code:这是我的代码:

In this, the function GetImages() returns the BitmapImages.在此,function GetImages GetImages()返回 BitmapImages。 PrintPreview is the grid where the BitmapImages are displayed. PrintPreview是显示 BitmapImages 的网格。

    public async Task PrintAsync()
    {
        GC.Collect();
        foreach (var image in await GetImages())
        {
            Grid grid = new Grid();
            var printpreview = new PrintPreview(image);
            grid.Children.Add(printpreview);

            printHelper.AddFrameworkElementToPrint(grid); printpreview = null;
            grid = null;
            GC.Collect();
        }
    }

Even though I force collect GC after the printing operation, the memory is not released.即使我在打印操作后强制收集 GC,memory 也没有释放。

    private void PrintHelper_OnPrintSucceeded()
    {
        GC.Collect();
        printHelper.ClearListOfPrintableFrameworkElements();
        printHelper.Dispose();
        GC.SuppressFinalize(this);

    }

Edit:编辑:

Below is the GetImages() function.下面是 GetImages() function。

    public async Task<IEnumerable<ImageSource>> GetImages(int qualityRatio = 2)
    {
        GC.Collect();
        if (pdf_stream != null)
        {
            StorageFolder myfolder = ApplicationData.Current.LocalFolder;
            StorageFile pdf_file;
            pdf_file = await myfolder.CreateFileAsync(filename + ".pdf", CreationCollisionOption.GenerateUniqueName);
            using (Stream outputStream = await pdf_file.OpenStreamForWriteAsync())
            {
                await pdf_stream.AsStreamForRead().CopyToAsync(outputStream);
            }
            var result = new List<ImageSource>();
            try
            {
                var document = await PdfDocument.LoadFromFileAsync(pdf_file);
                for (uint i = 0; i < document.PageCount; i++)
                {
                    using (var page = document.GetPage(i))
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            using (var randomStream = memoryStream.AsRandomAccessStream())
                            {
                                var image = new BitmapImage();
                                var options = new PdfPageRenderOptions
                                {
                                    DestinationWidth = (uint)page.Size.Width * (uint)qualityRatio,
                                    DestinationHeight = (uint)page.Size.Height * (uint)qualityRatio
                                };
                                await page.RenderToStreamAsync(randomStream, options);
                                image.SetSource(randomStream);
                                result.Add(image);
                            }
                        }
                    }
                }
            }
            catch { }
            return result;
        }
        return null;
    }

PrintPreview.xaml PrintPreview.xaml

<Page
x:Class="App.src.PrintPreview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
    <Image Source="{Binding}"   Stretch="Uniform" Margin="0"></Image>
</Grid>

PrintPreview.xaml.cs PrintPreview.xaml.cs

public sealed partial class PrintPreview : Page
{
    public PrintPreview(ImageSource image)
    {
        this.InitializeComponent();
        this.DataContext = image;
    }
}

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

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