释放PdfReader致Document、PdfWriter被释放引发异常的原因及解决
为什么释放PdfReader会导致Document/PdfWriter被意外释放?
问题背景
你在编写合并多个PDF第一页的代码时遇到了一个棘手的问题:用using语句自动释放PdfReader后,执行document.Close()时居然抛出了System.ObjectDisposedException,就好像Document和PdfWriter也被一起销毁了。虽然跳过释放PdfReader能暂时跑通代码,但显然不符合资源管理的最佳实践。
根因解析
这其实是iText库内部的引用关联机制导致的:当你通过writer.GetImportedPage(reader, 1)创建导入页时,PdfWriter会自动持有这个PdfReader的引用。默认情况下,当PdfReader被释放(也就是using块结束时),它会触发关联的PdfWriter释放相关资源——这就直接导致后续操作时,Document和PdfWriter已经处于被销毁的状态了。
解决方案
要解决这个问题,核心是在释放PdfReader之前,先让PdfWriter解除和它的绑定关系。iText提供了writer.FreeReader(reader)方法来做这件事,调用它之后,PdfWriter就不再持有该PdfReader的引用,此时再释放PdfReader就不会影响到Document和PdfWriter了。
修正后的完整代码如下:
using (FileStream fs = new FileStream(Path.Combine(pathPorducedPDFs, "function1.pdf"), FileMode.Create)) using (Document document = new Document(PageSize.A2)) using (PdfWriter writer = PdfWriter.GetInstance(document, fs)) { document.Open(); PdfContentByte cb = writer.DirectContent; foreach (string pdfPath in Directory.GetFiles(pathOriginalPDFs).OrderBy(x => x).ToList()) { using (PdfReader reader = new PdfReader(pdfPath)) { PdfImportedPage page = writer.GetImportedPage(reader, 1); document.NewPage(); cb.AddTemplate(page, 0, 0); document.Add(new Paragraph(pdfPath)); // 关键步骤:让Writer释放对当前Reader的引用 writer.FreeReader(reader); } } document.Close(); writer.Close(); fs.Close(); }
额外提示
- 一定要保留
using语句管理PdfReader,这是确保临时资源及时释放、避免内存泄漏的关键。 FreeReader是iText专门为这种多Reader复用Writer的场景设计的API,能安全清理Writer内部的关联缓存,不会影响后续的PDF生成操作。
内容的提问来源于stack exchange,提问作者Marco Salerno
相关产品推荐
相关产品推荐

