2010-03-11 15 views
5

Tôi muốn liên kết một hình ảnh với một số loại điều khiển để xóa nó sau này.Xóa một hình ảnh đã được sử dụng bởi một điều khiển WPF

path = @"c:\somePath\somePic.jpg" 
FileInfo fi = new FileInfo(path); 
Uri uri = new Uri(fi.FullName, UriKind.Absolute); 
var img = new System.Windows.Controls.Image(); 
img.Source = new BitmapImage(uri); 

Bây giờ sau khi mã này tôi muốn xóa các file:

fi.Delete(); 

Nhưng tôi không thể làm điều đó kể từ khi hình ảnh đang được sử dụng hiện nay. Giữa đoạn mã 1 vi 2 Tôi có thể làm gì để giải phóng nó?

Trả lời

3

sao chép các hình ảnh để MemoryStream trước khi đưa đến ImageSource nó sẽ giống như thế này

BitmapImage bi = new BitmapImage(); 
bi.BeginInit(); 
bi.DecodePixelWidth = 30; 
bi.StreamSource = byteStream; 
bi.EndInit(); 

nơi byteStream là bản sao của tập tin trong MemoryStream

cũng this có thể hữu ích

+2

Tx, nó hoạt động. Đối với người đọc sau này: Tôi đã sao chép nó vào một bộ nhớ như thế này: MemoryStream byteStream = new MemoryStream (File.ReadAllBytes (path)); – Peter

+1

Có nó hoạt động, ** nhưng nó không hiệu quả ** vì: 1. Hai bản sao của dữ liệu hình ảnh được lưu giữ mãi mãi, và 2. Bộ nhớ đệm bị bỏ qua để hình ảnh được tải ngay cả khi nó đã có trong RAM. Bài viết được liên kết giải thích cách giải quyết cho # 1 nhưng nó đòi hỏi nhiều mã bổ sung và vẫn không giải quyết đượC# 2. Một giải pháp tốt hơn là 'BitmapCacheOption.OnLoad' được kết hợp với' BeginInit/EndInit'. –

+0

Bạn không thể đóng luồng bộ nhớ sau 'EndInit'? Tại sao bạn cần phải giữ cả hai? – Jordan

11

Bạn có thể sử dụng một MemoryStream nhưng thực sự lãng phí bộ nhớ vì hai bản sao riêng biệt của dữ liệu bitmap được lưu trong RAM: Khi bạn tải MemoryStream, bạn tạo một bản sao và khi bitmap được giải mã một bản sao khác được thực hiện. Một vấn đề khác khi sử dụng MemoryStream theo cách này là bạn bỏ qua bộ nhớ cache.

Cách tốt nhất để làm điều này là để đọc trực tiếp từ tập tin sử dụng BitmapCacheOptions.OnLoad:

path = @"c:\somePath\somePic.jpg" 

var source = new BitmapImage(); 
source.BeginInit(); 
source.UriSource = new Uri(path, UriKind.RelativeOrAbsolute); 
source.CacheOption = BitmapCacheOption.OnLoad; 
source.EndInit(); // Required for full initialization to complete at this time 

var img = new System.Windows.Controls.Image { Source = source }; 

Giải pháp này là hiệu quả và đơn giản quá.

Lưu ý: Nếu bạn thực sự muốn bỏ qua bộ nhớ cache, ví dụ vì hình ảnh có thể thay đổi trên đĩa, bạn cũng nên đặt CreateOption = BitmapCreateOption.IgnoreImageCache. Nhưng ngay cả trong trường hợp đó giải pháp này tốt hơn giải pháp MemoryStream vì nó không giữ hai bản sao của dữ liệu hình ảnh trong RAM.

+0

Âm thanh thực sự tốt, nhưng tôi nhận được: * Không thể đặt trạng thái khởi tạo nhiều lần. * Tại * source.BeginInit(); * – Peter

+0

Xin lỗi: Tôi đã không kiểm tra mã bằng cách sử dụng quá tải hàm dựng cụ thể đó. Nó xuất hiện để gọi 'BeginInit()' và 'EndInit()' nội bộ. Tôi đã thay đổi mã để sử dụng các nhà xây dựng thường xuyên, mà nên khắc phục vấn đề đó. –

+1

Các vấn đề khác: 1. Tôi không thấy Nguồn là tài sản của lớp BitmapImage 2. Nếu tôi thay thế nó bằng UriSource, tôi vẫn nhận được rằng nó không được khởi tạo ... Nó hoạt động nếu tôi sử dụng nó như thế này : \t \t var source = new BitmapImage(); \t \t \t \t source.BeginInit(); \t \t \t \t source.UriSource = new Uri(path, UriKind.Absolute); \t \t \t \t source.CacheOption = BitmapCacheOption.OnLoad; \t \t \t \t source.EndInit(); +1 tuy nhiên với ý tưởng chính xác, thx. – Peter