Вопрос

In my WPF app, I am creating a FlowDocument by building its XAML markup as a string, and then using XamlReader.Parse to turn the string into a FlowDocument object, which I then save to an XPS document file. It works.

I needed to include an image in my document, and so to achieve this, I create and save the image as a temporary file in the temp directory, and then reference it with an absolute path in my FlowDocument's XAML. This works too - during the XPS document creation process, the image actually gets embedded into the XPS document, which is great.

But the problem is, my app retains a file lock on this image until the app quits.

I am cleaning up all resources. There is NO file lock on my generated XPS file - just the image file. If I comment out the part of my code which creates the XPS file, then the image file does not get locked.

My code (I'm on .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();
}

(Actually, the fact that's it's a dynamically generated image in the temp directory is irrelevant - this issue occurs if I hard code in the path of any image file on my machine - it will get locked.)

One would think that there is a bug in the XPS creation code that causes the file lock.

Is there something else I can try? Or a way to remove the file lock via code?

Это было полезно?

Решение

You could change your xaml like this instead:

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

to be able to play with the CacheOption parameter, to specify how the Xaml Builder should load the image file, as the default value seems to be keeping a lock on it (waiting for the GC to do its work it seems).

Here is some related question here on SO: How do you make sure WPF releases large BitmapSource from Memory?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top