我正在使用 Microsoft 的 PrintHelper(Microsoft.Toolkit.Uwp.Helpers.PrintHelper) 为我的应用程序打印 pdf。现在打印实际上是通过将 pdf 渲染到 BitmapImage
中,从而打印 BitmapImage
来工作的。这适用于少量页面。但是当页面数量增加时,用于渲染 BitmapImages 的内存消耗会增加。虽然我使用垃圾收集,但打印操作后内存不会释放。当执行打印次数过多时,应用程序会崩溃。
有什么方法可以减少这种内存泄漏或提高打印效率吗?
这是我的代码:
在此,函数 GetImages()
返回 BitmapImages。 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();
}
}
即使我在打印操作后强制收集GC,内存也没有释放。
private void PrintHelper_OnPrintSucceeded()
{
GC.Collect();
printHelper.ClearListOfPrintableFrameworkElements();
printHelper.Dispose();
GC.SuppressFinalize(this);
}
编辑:
下面是 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
<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
public sealed partial class PrintPreview : Page
{
public PrintPreview(ImageSource image)
{
this.InitializeComponent();
this.DataContext = image;
}
}
最佳答案
通过测试,可以额外创建一个Image控件,先将BitmapImage传给Image.Source,然后使用randomStream设置Source,会节省一些内存。
主页.xaml:
<Image x:Name="Output" Visibility="Collapsed" ></Image>
主页.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);
}
此外,我发现与使用流加载位图图像相比,使用urisource 可以节省更多内存。但是您需要将每个页面从 pdf 转换为 StorageFile 并将其保存在临时文件夹中,然后使用 UriSource 将其转换为 bitmapImage。比较复杂,不过也可以试试看。
关于c# - 如何在 UWP 应用程序中打印 pdf 文件后减少内存消耗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58875913/