2009-11-02 97 views
3

我在WPF中有一個問題,在應用程序的另一部分嘗試寫入圖像之前,窗口沒有在關閉之後釋放它的背景圖像文件上的文件鎖定。刪除一個窗口的背景圖像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();看看是否能治癒這個問題,但事實並非如此。

回答

4

托馬斯給出的答案是正確的,效果很好,如果你有一個文件路徑,不想要緩存位圖,而不想使用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將不會進入磁盤。在您的特定應用中,這可能是一件壞事,但對於其他用途,它可能是一個理想的功能。
+0

這是燦爛的,謝謝你們倆! – Siyfion 2009-11-02 18:39:09

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

其實它比這還糟糕:backgroundBrush.ImageSource = new BitmapImage(new Uri(Constants。ShellLocation + @「Background \ TempBkgrnd.png」,UriKind.Absolute)); – Siyfion 2009-11-02 14:23:16