加载后流处理时,Windows应用商店应用程序PDF文档不会呈现



我有一个工作解决方案,可以从Windows应用商店应用程序中的字节数组加载和呈现PDF文档。不过,最近一些用户报告了内存不足的错误。正如你在下面的代码中看到的,有一个流我没有处理掉。我已经把这句话评论掉了。如果我真的处理了那个流,那么PDF文档就不会再呈现了。它只是显示了一个完全白色的图像。有人能解释为什么以及如何加载和呈现PDF文档并处理所有一次性用品吗?

private static async Task<PdfDocument> LoadDocumentAsync(byte[] bytes)
{
    using (var stream = new InMemoryRandomAccessStream())
    {
        await stream.WriteAsync(bytes.AsBuffer());
        stream.Seek(0);
        var fileStream = RandomAccessStreamReference.CreateFromStream(stream);
        var inputStream = await fileStream.OpenReadAsync();
        try
        {
            return await PdfDocument.LoadFromStreamAsync(inputStream);
        }
        finally
        {
            // do not dispose otherwise pdf does not load / render correctly. Not disposing though may cause memory issues.
            // inputStream.Dispose();
        }
    }
}

以及呈现PDF 的代码

private static async Task<ObservableCollection<BitmapImage>> RenderPagesAsync(
    PdfDocument document, 
    PdfPageRenderOptions options)
{
    var items = new ObservableCollection<BitmapImage>();
    if (document != null && document.PageCount > 0)
    {
        for (var pageIndex = 0; pageIndex < document.PageCount; pageIndex++)
        {
            using (var page = document.GetPage((uint)pageIndex))
            {
                using (var imageStream = new InMemoryRandomAccessStream())
                {
                    await page.RenderToStreamAsync(imageStream, options);
                    await imageStream.FlushAsync();
                    var renderStream = RandomAccessStreamReference.CreateFromStream(imageStream);
                    using (var stream = await renderStream.OpenReadAsync())
                    {
                        var bitmapImage = new BitmapImage();
                        await bitmapImage.SetSourceAsync(stream);
                        items.Add(bitmapImage);
                    }
                }
            }
        }
    }
    return items;
}

正如你所看到的,我在两个方法中都使用了RandomAccessStreamReference.CreateFromStream方法。我见过其他例子跳过这一步,直接使用InMemoryRandomAccessStream加载PDF文档或位图图像,但当时我还没能正确渲染PDF。图像将再次完全变白。正如我上面提到的,这段代码确实正确地呈现了PDF,但并没有处理掉所有可丢弃的东西。

为什么

我假设LoadFromStreamAsync(IRandomAccessStream)不会将整个流解析为PdfDocument对象,而是只解析主要的PDF字典并保存对IRandomAccessStream的引用。

这实际上是明智的做法,如果用户最终只想呈现一个页面,甚至只想查询页面数量,为什么要将整个PDF解析成自己的对象(从资源角度来看,这可能是一项非常昂贵的操作)

稍后,当调用返回的PdfDocument的其他方法(例如GetPage)时,这些方法尝试从流中读取它们执行任务(例如渲染)所需的附加数据。不幸的是,在您的情况下,这意味着在finally { inputStream.Dispose(); } 之后

其他怎么办

您必须推迟inputStream.Dispose(),直到PdfDocument上的所有操作完成。这意味着您的代码可能会有一些细微的体系结构更改。可能将LoadDocumentAsync代码作为帧移动到RenderPagesAsync方法或其调用者中就足够了。

相关内容

  • 没有找到相关文章

最新更新