【问题标题】:Does the WPF DocumentPaginator keep all DocumentPages in memory until it finishes a print job?WPF DocumentPaginator 是否将所有 DocumentPages 保留在内存中,直到完成打印作业?
【发布时间】:2011-07-20 01:42:18
【问题描述】:

关于 WPF 的 DocumentPaginator 的严格理论问题:

当使用 WPF DocumentPaginator 类打印多页文档时,分页器是否将其请求的所有 DocumentPages 保留在内存中,直到文档完成打印为止?或者它是否曾经在打印作业完成之前处理掉不再需要的任何 DocumentPages(即释放内存)?有没有办法在打印过程中手动告诉分页器释放旧的/不需要的 DocumentPages 而不会遇到异常?

非常感谢您在这方面的帮助!

【问题讨论】:

    标签: wpf out-of-memory objectdisposedexception documentpage documentpaginator


    【解决方案1】:

    我遇到了和你一样的问题。

    它不会处理较早加载的页面。我解决这个问题的方法是在 GetPage() 方法的末尾保存对加载页面的引用,并在 GetPage 方法的开头处理最后加载的页面。

    这里是您附加问题的答案:

    我的印象是 System.Windows.Controls.PrintDialog.Print(DocumentPaginator, title) 的实现是这样的:

    Public void PrintDocument(DocumentPaginator paginator, string title)
    {
       Dictionary<int, DocumentPage> pages = new Dictionary<int DocumentPage>();
       for(int i=0; i<paginator.PageCount(); i++)
       {
          pages.Add(i, paginator.GetPage(i));
          UnknownPrinterEngine.SendPageToPrinter(pages(i)); //this is just imagination
       }
    }
    

    如果实现确实是这样,则对每个已处理页面的本地引用将保持活动状态(在字典中),直到方法执行完成。 --> 不会释放任何内存。

    我做了什么来避免这种情况(扩展 DocumentPaginator 的类中的 GetPage 实现):

    DocumentPage lastLoadedPage = null;
    public DocumentPage GetPage(int pageNumber)
    {
       if(lastLoadedPage != null)
       {
          lastLoadedPage.Dispose()
       }
       //MyPrintControl should be your custom UserControl which represents the page to print
       myPrintControl pageContent = new MyPrintControl();
       pageContent.Width = PageSize.Width;
       pageContent.Height = PageSize.Height;
    
       pageContent.Measure(PageSize);
       pageContent.Arrange(new Rect(new Point(0,0), PageSize));
    
       DocumentPage actualPage = New DocumentPage(pageContent);
       lastLoadedPage = actualPage;
       return actualPage;
    }
    

    最后你应该实现 IDisposable 接口并在 Dispose 方法中清理 lastLoadedPage 字段以释放最后一页的内存。

    【讨论】:

    • 感谢您的快速回复,fantasyfix。您能否澄清一下“gard[ing](保护?)在 GetPage() 方法末尾对加载页面的引用”是什么意思?您是否使用静态变量来存储引用(即它会保留到下一次调用 GetPage ......虽然我不确定这是正确的,因为我是 C# 新手)?您是否通过引用将上一页作为另一个参数传入(即将函数签名从 GetPage (int pageNumber) 更改为 GetPage (int pageNumber, ref DocumentPage previous))?
    • 编辑了里面的答案,希望你明白我的意思。
    • 嗯...我试过了,但它似乎没有释放任何内存(我通过使用 Performance Manager 观察私有字节分配来验证性能)。
    • 请注意:根据 MSDN 文档(以及我使用 Visual Studio 运行的代码),DocumentPage 的构造函数始终需要至少一个参数(至少是一个 Visual 对象)。所以我猜你创建一个新 DocumentPage 的代码看起来和你上面的不完全一样(即使用像 new DocumentPage() 这样的语法)?
    • 是的,没错,我就是这样编写代码的,我将它与 Visual 一起使用。所以它将是 DocumentPage page = new DocumentPage(visualToPrint)。
    【解决方案2】:

    查看System.Windows.Xps.VisualsToXpsDocument 这解决了我在创建大型 xps 文档时内存不足的问题。另请查看 PrintQueue.CreateXpsDocumentWriter(somePrintQueue) 。抱歉,我没有足够的代表来发表评论。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 2017-01-20
      • 2019-05-08
      • 1970-01-01
      • 2018-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多