Удаление фонового изображения окна WPF - PullRequest
3 голосов
/ 02 ноября 2009

У меня проблема в WPF, когда окно не освобождает свою блокировку файла для файла фонового изображения после закрытия до того, как другая часть приложения попытается выполнить запись в изображение.

Так в качестве примера; скажем, у меня есть приложение WPF, состоящее из 3 окон, 1 окна выбора «меню» и 2 других. Оба окна создают ImageBrush, используя BitmapImage в качестве ImageSource (* то же изображение).

В окне 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 голосов
/ 02 ноября 2009

Томас дал правильный ответ и хорошо работает, если у вас есть путь к файлу, вы не хотите кэшировать растровое изображение и не хотите использовать XAML.

Однако следует также отметить, что BitmapImage имеет встроенный способ немедленной загрузки растрового изображения путем установки BitmapCacheOption:

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

или

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

Это немедленно загрузит растровое изображение и явным образом закроет поток, как при использовании FileStream, но с некоторыми отличиями:

  • Он будет работать с любым Uri, например пакетом: // Uri.
  • Может использоваться напрямую из XAML
  • Растровое изображение кэшируется в кэше растрового изображения, поэтому в будущем использование того же Uri не попадет на диск. В вашем конкретном приложении это может быть плохо, но для других целей это может быть желательной функцией.
2 голосов
/ 02 ноября 2009

Полагаю, вы загружаете изображение прямо из файла, вот так?

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