【问题标题】:WPF DocumentViewer doesn't release the XPS fileWPF DocumentViewer 不发布 XPS 文件
【发布时间】:2010-09-21 22:24:06
【问题描述】:

我正在开发一个可打开并显示 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 文档,会弹出一个异常,指出要删除的文件仍在使用中。

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

谢谢!

【问题讨论】:

    标签: .net wpf xps documentviewer


    【解决方案1】:

    您需要关闭打开分配给查看器的 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);
    

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 嘿,这个成功了!我只是让 XpsDocument 对象保持打开状态,并且只在退出期间调用 XpsDocument.Close() 并且我能够删除该文件。谢谢穆格斯!
      • 这仅在您可以关闭应用程序以释放锁定时才有效。如果您需要在您的应用程序保持打开状态时释放锁,您需要在下面或stackoverflow.com/questions/1442607/… 中查看我的答案
      【解决方案3】:

      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) 获取托管堆栈跟踪并四处寻找

      【讨论】:

        【解决方案4】:

        感谢您的回复!

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

        【讨论】:

          【解决方案5】:

          没有,到目前为止还没有。

          只是列举一下,我尝试了以下失败的方法:

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

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

          DocumentViewer 错误???

          【讨论】:

            【解决方案6】:

            我怀疑你遇到了同样的问题 http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic59281.aspx

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

            【讨论】:

              猜你喜欢
              • 2018-02-13
              • 2010-11-29
              • 2023-03-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-09-16
              • 1970-01-01
              • 2010-10-04
              相关资源
              最近更新 更多