3

我在 WPF 中遇到问题,在应用程序的另一部分尝试写入图像之前,窗口在关闭后没有释放背景图像文件上的文件锁定。

举个例子;假设我有一个由 3 个窗口、1 个“菜单”选择窗口和 2 个其他窗口组成的 WPF 应用程序。两个窗口都ImageBrush使用 aBitmapImage作为ImageSource相同的图像)创建一个。

窗口 A 有一个按钮,当按下该按钮时,通过将它们分别复制到用作原始文件的文件上ImageSource并创建一个新的ImageBrush并将其设置Window.Background为新画笔来循环显示可用的背景图像。

窗口 B 只是使用ImageBrush来绘制Window.Background.

如果窗口 A 启动,背景切换,关闭,然后窗口 B 启动,一切都很好。

如果 Window B 启动,然后关闭,则 Window A 启动并且背景切换它崩溃。尝试切换背景会引发IOException因为:

“该进程无法访问文件'C:\Backgrounds\Background.png',因为它正被另一个进程使用。”

所以窗口 B 一定还在以某种方式抓住它!?我试过做一个GC.Collect(); GC.WaitForPendingFinalizers();看看这是否能解决问题,但它没有。

4

2 回答 2

4

Thomas 给出的答案是正确的,如果您有文件路径、不想缓存位图并且不想使用 XAML,则效果很好。

但是还应该提到的是,BitmapImage 有一个内置的方法来通过设置 BitmapCacheOption 立即加载位图:

BitmapImage img = new BitmapImage { CacheOption = BitmapCacheOption.OnLoad };
img.BeginInit();
img.UriSource = imageUrl;
img.EndInit();

或者

<BitmapImage CacheOption="OnLoad" UriSource="..." />

这将立即加载位图并显式关闭流,就像使用 FileStream 一样,但有几个不同之处:

  • 它适用于任何 Uri,例如 pack:// Uri。
  • 它可以直接从 XAML 中使用
  • 位图缓存在位图缓存中,因此将来使用相同的 Uri 不会进入磁盘。在您的特定应用程序中,这可能是一件坏事,但对于其他用途,它可能是一个理想的功能。
于 2009-11-02T17:33:34.167 回答
2

我假设您是直接从文件中加载图像,就像那样?

BitmapImage img = new BitmapImage();
img.BeginInit();
img.UriSource = imageUrl;
img.EndInit();

尝试从流中加载它;这样,您可以在加载图像后自己关闭流,这样文件就不会被锁定:

BitmapImage img = new BitmapImage();
using (FileStream fs = File.OpenRead(imageFilePath)
{
    img.BeginInit();
    img.StreamSource = fs;
    img.EndInit();
}
于 2009-11-02T14:21:20.030 回答