删除WPF窗口背景图像

3
我在WPF中遇到了一个问题,即窗口在关闭后没有释放背景图片文件的文件锁,然后应用程序的另一部分尝试写入该图像时出现问题。
举个例子:假设我有一个由3个窗口组成的WPF应用程序,其中1个是“菜单”选择窗口,另外2个是其他窗口。这两个窗口都使用BitmapImage作为ImageSource创建ImageBrush(使用相同的图像)。
窗口A有一个按钮,按下后会通过将每个可用的背景图像复制到用作原始ImageSource的文件上,并创建一个新的ImageBrush来循环显示它们,并设置Window.Background为新刷子。
窗口B仅使用ImageBrush绘制Window.Background
如果启动窗口A,切换背景,关闭窗口,然后启动窗口B,一切正常。
如果先启动窗口B,关闭窗口,然后再启动窗口A并切换背景,则会崩溃。尝试切换背景会抛出IOException,因为:“进程无法访问文件'C:\Backgrounds\Background.png',因为另一个进程正在使用它。”
因此,窗口B必须仍然以某种方式持有它!?我尝试使用GC.Collect(); GC.WaitForPendingFinalizers();来查看是否可以解决问题,但是没有效果。
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的将来使用不会访问磁盘。 在您特定的应用程序中,这可能是不好的事情,但对于其他用途,这可能是一个理想的功能。

我猜在 BeginInit() 之前设置 CacheOption = BitmapCacheOption.OnLoad 并不起作用!? - mkb

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();
}

实际上情况比那更糟:backgroundBrush.ImageSource = new BitmapImage(new Uri(Constants.ShellLocation + @"Background\TempBkgrnd.png", UriKind.Absolute)); - Siyfion

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