Excluindo a imagem de fundo de uma janela WPF
-
12-09-2019 - |
Pergunta
Estou tendo um problema no WPF, onde uma janela não libera seu bloqueio de arquivo no arquivo de imagem em segundo plano após o fechamento, antes que outra parte do aplicativo tenta gravar na imagem.
Então, como exemplo; Digamos que eu tenha um aplicativo WPF composto por 3 janelas, 1 janela de seleção de "menu" e 2 outras. Ambas as janelas criam um ImageBrush
usando um BitmapImage
Enquanto o ImageSource
(a mesmo imagem).
A janela A tem um botão que, quando pressionado, percorre as imagens de fundo disponíveis, copiando -as sobre o arquivo usado como original ImageSource
e criando um novo ImageBrush
e definir o Window.Background
para o novo pincel.
A janela B simplesmente usa o ImageBrush
para desenhar o Window.Background
.
Se a janela A for iniciada, os fundos alternados, fechados e depois a janela B iniciada, tudo está bem.
Se a janela B for iniciada, fechada, a janela A será iniciada e os fundos trocados, ele trava. Tentando mudar de fundo joga um IOException
Porque:
"O processo não pode acessar o arquivo 'c: backgrounds background.png' porque está sendo usado por outro processo".
Então a janela B ainda deve estar segurando -o de alguma forma!? Eu tentei fazer um GC.Collect(); GC.WaitForPendingFinalizers();
Para ver se isso cura o problema, mas não.
Solução
A resposta que Thomas deu está correta e funciona bem se você tiver um caminho de arquivo, não deseja armazenar em cache o bitmap e não quiser usar o XAML.
No entanto, também deve-se mencionar que o Bitmapimage possui uma maneira interna de carregar o bitmap imediatamente definindo o BitmapCacheOption:
BitmapImage img = new BitmapImage { CacheOption = BitmapCacheOption.OnLoad };
img.BeginInit();
img.UriSource = imageUrl;
img.EndInit();
ou
<BitmapImage CacheOption="OnLoad" UriSource="..." />
Isso carregará o bitmap imediatamente e fechará explicitamente o fluxo, assim como o uso de uma transmissão filtro, mas com várias diferenças:
- Funcionará com qualquer URI, como um pacote: // URI.
- Pode ser usado diretamente de xaml
- O bitmap é armazenado em cache no cache do bitmap, portanto, o uso futuro do mesmo URI não vai para o disco. Em seu aplicativo específico, isso pode ser uma coisa ruim, mas para outros usos pode ser um recurso desejável.
Outras dicas
Presumo que você esteja carregando a imagem diretamente do arquivo, assim?
BitmapImage img = new BitmapImage();
img.BeginInit();
img.UriSource = imageUrl;
img.EndInit();
Tente carregá -lo de um fluxo; Dessa forma, você pode fechar o fluxo depois que a imagem é carregada, para que o arquivo não esteja bloqueado:
BitmapImage img = new BitmapImage();
using (FileStream fs = File.OpenRead(imageFilePath)
{
img.BeginInit();
img.StreamSource = fs;
img.EndInit();
}