【问题标题】:Windows Store App PDF Document does not render when stream disposed after load加载后处理流时,Windows Store App PDF 文档不呈现
【发布时间】:2014-10-31 15:11:33
【问题描述】:

我有一个可行的解决方案,可以从 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,但并没有处理掉所有的一次性用品。

【问题讨论】:

    标签: c# pdf stream windows-store-apps dispose


    【解决方案1】:

    为什么

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

    这实际上是明智的做法,如果用户最终只想渲染一个页面,或者甚至只想查询,为什么要将整个 PDF 解析为自己的对象(在资源方面可能非常昂贵的操作)页数...

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

    怎么办

    您必须推迟inputStream.Dispose(),直到PdfDocument 上的所有操作完成。这意味着对您的代码进行一些有希望的微小架构更改。可能将 LoadDocumentAsync 代码作为框架移动到 RenderPagesAsync 方法或其调用者中就足够了。

    【讨论】:

    猜你喜欢
    • 2017-04-14
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多