我正在通过 IIS Web 应用程序合并 XPS 文件,但在合并过程中,它使文档参考文件句柄保持打开状态。在 Windows WPF 或控制台应用程序中,我不会担心句柄,因为它们会在应用程序关闭后被释放。回收应用程序池也会有效地关闭句柄。但是,由于缓存和性能,我不能仅仅为了关闭文件句柄而回收应用程序池。
合并完成后有没有办法关闭这些文件句柄?我尝试了几种不同的合并方法,但以下代码给了我最好的结果:
private DocumentPaginator CreateMergedDocument(IEnumerable<string> xpsFiles) {
using ( MemoryStream mergedStream = new MemoryStream() ) {
using ( var pkg = Package.Open( mergedStream, FileMode.Create, FileAccess.ReadWrite ) ) {
var pack = "pack://merged.xps";
var uri = new Uri( pack, UriKind.Absolute );
PackageStore.AddPackage( uri, pkg );
using ( XpsDocument mergedDocument =
new XpsDocument( pkg, CompressionOption.Maximum, pack ) ) {
FixedDocumentSequence seqNew = new FixedDocumentSequence();
foreach ( string sourceDocument in xpsFiles ) {
using ( XpsDocument xpsOld =
new XpsDocument( sourceDocument, FileAccess.Read ) ) {
FixedDocumentSequence seqOld = xpsOld.GetFixedDocumentSequence();
foreach ( DocumentReference dr in seqOld.References ) {
DocumentReference newDocumentReference = new DocumentReference();
newDocumentReference.Source = dr.Source;
( newDocumentReference as IUriContext ).BaseUri =
( dr as IUriContext ).BaseUri;
seqNew.References.Add( newDocumentReference );
}
}
}
XpsDocumentWriter xpsWriter = XpsDocument.CreateXpsDocumentWriter( mergedDocument );
xpsWriter.Write( seqNew );
PackageStore.RemovePackage( uri );
return seqNew.DocumentPaginator;
}
}
}
}
我追踪了打开xpsWriter.Write(seqNew)
代码行的文件句柄。这是预期的,因为它需要加载文件以复制到新的FixedDocumentSequence
. XpsDocumentWriter
但是,如果 an是一次性的并清理了它的非托管资源/文件句柄,那就太好了。
在我的研究过程中,我尝试了其他一些方法。我尝试过的一种方法是将每个页面可视化写入SerializerWriterCollator
. 我研究过的另一种方法是处理 FixedPage 内容并将 URI 更新为复制的图像和字体流,并将原始 XAML 写回到XmlWriter
. 两者都没有很好地工作。使用页面视觉效果和SerializerWriterCollator
,我在合并的 XPS 上获得了不正确的页面大小,并且它正在切断内容。使用原始XmlWriter
方法时,合并的 XPS 中的一些图像会混杂在一起,并且会错误地显示一些页面内容。