在WPF中创建XPS - 使用的图像文件被锁定直到我的应用程序退出

4
在我的WPF应用程序中,我通过构建其XAML标记作为字符串来创建FlowDocument,然后使用XamlReader.Parse将字符串转换为FlowDocument对象,然后将其保存到XPS文档文件。它运行良好。
我需要在文档中包含一个图像,因此为了实现这一点,我创建并保存图像作为临时文件在临时目录中,并在我的FlowDocument的XAML中引用它的绝对路径。这也可以正常工作-在XPS文档创建过程中,图像实际上被嵌入到XPS文档中,这很好。
但问题是,我的应用程序保留了对该图像的文件锁定,直到应用程序退出。
我正在清理所有资源。我的生成的XPS文件上没有文件锁定-只有图像文件。如果我注释掉创建XPS文件的代码部分,那么图像文件就不会被锁定。
我的代码(我正在使用.NET 4 CP):
var xamlBuilder = new StringBuilder();

// many lines of code like this
xamlBuilder.Append(...);

// create and save image file
// THE IMAGE AT THE PATH imageFilePath IS GETTING LOCKED
// AFTER CREATING THE XPS FILE
var fileName = string.Concat(Guid.NewGuid().ToString(), ".png");
var imageFilePath = string.Format("{0}{1}", Path.GetTempPath(), fileName);
using (var stream = new FileStream(imageFilePath, FileMode.Create)) {
  var encoder = new PngBitmapEncoder();
  using (var ms = new MemoryStream(myBinaryImageData)) {
    encoder.Frames.Add(BitmapFrame.Create(ms));
    encoder.Save(stream);
  }
  stream.Close();
}

// add the image to the document by absolute path
xamlBuilder.AppendFormat("<Paragraph><Image Source=\"{0}\" ...", imageFilePath);

// more lines like this
xamlBuilder.Append(...);

// create a FlowDocument from the built string
var document = (FlowDocument) XamlReader.Parse(xamlBuilder.ToString());

// set document settings
document.PageWidth = ...;
...

// save to XPS file
// THE XPS FILE IS NOT LOCKED. IF I LEAVE OUT THIS CODE
// AND DO NOT CREATE THE XPS FILE, THEN THE IMAGE IS NOT LOCKED AT ALL
using (var xpsDocument = new XpsDocument(filePath, FileAccess.ReadWrite)) {
  var documentWriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
  documentWriter.Write(((IDocumentPaginatorSource) document).DocumentPaginator);
  xpsDocument.Close();
}

(实际上,它是在临时目录中动态生成的图像这一事实并不重要 - 如果我硬编码任何计算机上的图像文件路径,它都会被锁定。)

人们可能会认为 XPS 创建代码中存在导致文件锁定的 bug。

还有其他什么我可以尝试吗?或者有没有办法通过代码来解除文件锁定?


我曾经也遇到过同样的问题。不过我设法解决了。让我看看是否能在某个地方找到我提出的问题(如果我确实在这里提出了)。我想它与使用“Freeze()”方法来冻结图像有关。 - Mathias Lykkegaard Lorenzen
在FlowDocument标记中,我尝试添加了po:Freeze="True"属性(在根标记中使用xmlns:po声明)- 不幸的是没有起作用。 - Ross
你尝试过像这样声明图像吗:<Image><Image.Source><BitmapImage CacheOption="None" UriSource="你的路径" /></Image.Source></Image> - Simon Mourier
谢谢Simon。不幸的是,“None”对于CacheOption没有起作用。但它引导我进行了一次搜索,我在这个页面上找到了解决方法:http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic59281.aspx,其中用户通过使用“OnLoad” CacheOption来防止文件锁定。所以我也这样做了,现在它可以工作了!太棒了。 - Ross
顺便说一句,您提供答案后我会授予悬赏,如果没有您的帮助,我是想不出来的。 - Ross
1个回答

2
你可以像这样改变你的XAML:

你可以这样改变你的XAML:

<Image>
    <Image.Source>
        <BitmapImage CacheOption="None" UriSource="your path" />
    </Image.Source>
</Image>

为了能够使用CacheOption参数,指定Xaml Builder应如何加载图像文件,因为默认值似乎会对其进行锁定(似乎在等待GC完成其工作)。

这里有一些相关的问题:如何确保WPF释放内存中的大型BitmapSource?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接