10

我正在开发一个打开并显示 XPS 文档的 WPF 应用程序。当应用程序关闭时,规范是应用程序应删除打开的 XPS 文档以进行清理。但是,当打开某个 XPS 文档时,应用程序会在尝试删除该文件时抛出该文件仍在使用中的异常。这有点奇怪,因为它仅在打开特定的 XPS 文档时发生,并且仅在您超出第一页时才会发生。

我使用的一些代码如下所示:

打开 XPS 文档:

DocumentViewer m_documentViewer = new DocumentViewer();
XpsDocument m_xpsDocument = new XpsDocument(xpsfilename, fileaccess);
m_documentViewer.Document = m_xpsDocument.GetFixedDocumentSequence();
m_xpsDocument.Close();

导航 XPS 文档:

m_documentViewer.FirstPage();
m_documentViewer.LastPage();
m_documentViewer.PreviousPage();
m_documentViewer.NextPage();

关闭 DocumentViewer 对象并删除文件:

m_documentViewer.Document = null;
m_documentViewer = null;
File.Delete(xpsfilename);

这一切都非常基本,并且可以与我们测试的其他文档一起使用。但是对于特定的 XPS 文档,会弹出一个异常,指出要删除的文件仍在使用中。

我的代码有什么问题或遗漏吗?

谢谢!

4

6 回答 6

7

您需要关闭打开分配给查看器的 XpsDocument 的 System.IO.Packaging.Package。此外,如果您希望能够在同一个应用程序会话中再次打开同一个文件,则必须从 PackageStore 中删除该包。

尝试

var myXpsFile = @"c:\path\to\My XPS File.xps";
var myXpsDocument = new XpsDocument(myXpsFile);
MyDocumentViewer.Document = myXpsDocument;

//open MyDocumentViwer's Window and then close it
//NOTE: at this point your DocumentViewer still has a lock on your XPS file
//even if you Close() it
//but we need to do something else instead

//Get the Uri from which the system opened the XpsPackage and so your XpsDocument
var myXpsUri = myXpsDocument.Uri; //should point to the same file as myXpsFile

//Get the XpsPackage itself
var theXpsPackage = System.IO.Packaging.PackageStore.GetPackage(myXpsUri);

//THIS IS THE KEY!!!! close it and make it let go of it's file locks
theXpsPackage.Close();

File.Delete(myXpsFile); //this should work now

//if you don't remove the package from the PackageStore, you won't be able to
//re-open the same file again later (due to System.IO.Packaging's Package store/caching
//rather than because of any file locks)
System.IO.Packaging.PackageStore.RemovePackage(myXpsUri);

是的,我知道您可能没有打开带有 Package 的 XpsDocument,甚至可能不知道它是什么——或关心它——但是 .NET 在幕后为您“完成”了它并且忘记了自己清理。

于 2009-09-02T21:24:52.670 回答
2

使 xpsDocument 成为成员,然后不要在其上调用 close() :)

于 2008-11-14T07:46:06.217 回答
0

http://blogs.msdn.com/junfeng/archive/2008/04/21/use-htrace-to-debug-handle-leak.aspx

您可以使用 WinDbg 找出谁拥有句柄和非托管堆栈

编辑:当然,您还可以通过 SOS 扩展 ( http://msdn.microsoft.com/en-us/library/bb190764.aspx )获取托管堆栈跟踪和查看

于 2008-11-12T05:07:14.563 回答
0

谢谢回复!

这有点低级,但当我用完想法时,我会记住它。无论如何,我发现了更多关于这个错误的信息。导致异常的特定文档中插入了图像。当我删除图像时,不会发生异常。这可能是 DocumentViewer 错误,但我仍在尝试......

于 2008-11-13T08:19:11.740 回答
0

没有,到现在还一无所获。

举个例子,我尝试了以下失败的方法:

  1. 在删除文件之前,在窗口的“关闭”事件中将所有内容设置为空。这包括 DocumentViewer.Document 属性和 DocumentViewer 对象。

  2. 使用 ShowDialog() 打开窗口,然后将其设置为 null。将文件的删除移至打开窗口的 System.Windows.Application 对象的“退出”事件。仍然抛出文件正在被使用的异常。

文档查看器错误???

于 2008-11-14T03:11:18.660 回答
0

我怀疑您遇到与http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic59281.aspx相同的问题

听起来像 DocumentViewer 中的一个错误,它应该在关闭时处理嵌套的 BitmapDecoders 或使用不同的位图缓存选项加载图像。

于 2008-12-19T09:54:03.373 回答