删除窗口的背景图像 WPF

发布于 2024-08-10 13:31:16 字数 746 浏览 4 评论 0原文

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

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

窗口 A 有一个按钮,按下该按钮后,将循环显示可用的背景图像,方法是将它们复制到用作原始 ImageSource 的文件上,创建一个新的 ImageBrush 并设置 < code>Window.Background 到新画笔。

窗口 B 仅使用 ImageBrush 绘制 Window.Background

如果启动窗口 A,切换背景,关闭,然后启动窗口 B,则一切正常。

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

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

那么B窗一定还以某种方式保留着它!?我尝试过执行 GC.Collect(); GC.WaitForPendingFinalizers(); 看看是否可以解决问题,但事实并非如此。

I'm having a problem in WPF where a window doesn't release it's file-lock on the background image file after closing, before another part of the application tries to write to the image.

So as an example; say I have a WPF app consisting of 3 windows, 1 "menu" selection window and 2 others. Both of the windows create an ImageBrush using a BitmapImage as the ImageSource (the same image).

Window A has a button that when pressed, cycles through the available background images by copying them each over the file used as the original ImageSource and creating a new ImageBrush and setting the Window.Background to the new brush.

Window B simply uses the ImageBrush to draw the Window.Background.

If Window A is launched, backgrounds switched, closed and then Window B launched, everything is fine.

If Window B is launched, closed, then Window A is launched and backgrounds switched it crashes. Trying to switch the backgrounds throws an IOException because:

"The process cannot access the file 'C:\Backgrounds\Background.png' because it is being used by another process."

So Window B must still be holding onto it somehow!? I have tried doing a GC.Collect(); GC.WaitForPendingFinalizers(); to see if that cures the problem but it doesn't.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

驱逐舰岛风号 2024-08-17 13:31:16

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 不会去磁盘。在您的特定应用程序中,这可能是一件坏事,但对于其他用途来说,这可能是一个理想的功能。

The answer Thomas gave is correct, and works well if you have a file path, don't want to cache the bitmap, and don't want to use XAML.

However it should also be mentioned that BitmapImage has a built-in way to load the bitmap immediately by setting BitmapCacheOption:

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

or

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

This will load the bitmap immediately and explicitly close the stream, just as using a FileStream would, but with several differences:

  • It will work with any Uri, such as a pack:// Uri.
  • It can be used directly from XAML
  • The bitmap is cached in the bitmap cache, so future use of the same Uri won't go to the disk. In your particular application this may be a bad thing, but for other uses it may be a desirable feature.
提笔落墨 2024-08-17 13:31:16

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

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

I assume you're loading the image directly from the file, like that ?

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

Try to load it from a stream instead ; that way you can close the stream yourself after the image is loaded, so that the file isn't locked :

BitmapImage img = new BitmapImage();
using (FileStream fs = File.OpenRead(imageFilePath)
{
    img.BeginInit();
    img.StreamSource = fs;
    img.EndInit();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文