2010-10-02 29 views
12

Có thể sử dụng phương pháp FromStream của System.Drawing.Image mà không phải giữ luồng mở trong suốt thời gian của hình ảnh không?Tải hình ảnh từ luồng mà không giữ luồng mở

Tôi có một ứng dụng tải một loạt đồ họa trên thanh công cụ từ các tệp tài nguyên, sử dụng kết hợp Image.FromStreamAssembly.GetManifestResourceStream.

Sự cố tôi gặp phải trong khi hoạt động tốt trên Windows 7, trên Windows XP, ứng dụng bị treo nếu phần tử giao diện người dùng được liên kết với một trong những hình ảnh này bị tắt. Trên Windows 7, hình ảnh được hiển thị bằng màu xám. Trên XP, nó bị treo với một ngoại lệ bộ nhớ.

Sau khi tải trọng sợi tóc, tôi cuối cùng đã truy tìm nó để tải ban đầu của hình ảnh. Như một vấn đề tất nhiên, nếu tôi có thể tạo bất kỳ đối tượng thực hiện IDisposable đó cũng bị phá hủy trong các phương pháp tương tự, tôi quấn nó trong một tuyên bố sử dụng, ví dụ

using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName)) 
{ 
    image = Image.FromStream(resourceStream); 
} 

Nếu tôi loại bỏ các tuyên bố sử dụng để các isn suối 't xử lý, sau đó ứng dụng không còn treo trên XP. Nhưng bây giờ tôi có một loạt các dòng "mồ côi" treo quanh - các hình ảnh được lưu trữ trong các lớp lệnh và những hình ảnh này được xử lý một cách chính xác khi chúng được xử lý, nhưng luồng ban đầu thì không.

Tôi đã kiểm tra tài liệu cho FromStream và xác nhận rằng luồng cần phải vẫn mở. Tại sao điều này đã không bị rơi và đốt cháy trên hệ thống phát triển Windows 7 là một bí ẩn tuy nhiên!

Tôi thực sự không muốn luồng này treo xung quanh và tôi chắc chắn không muốn lưu trữ tham chiếu tới luồng này cũng như hình ảnh để tôi có thể xử lý nó sau này. Tôi chỉ có nhu cầu của dòng đó một lần vì vậy tôi muốn để thoát khỏi nó :)

Có thể tạo hình ảnh và sau đó giết luồng ở đó không?

+3

Vào cách, một 'OutOfMemoryException' trong' System.Drawing' có nghĩa là * lỗi chung * trong GDI +. Lý do cho điều này là [historical] (http://stackoverflow.com/questions/2610416/is-there-a-reason-image-fromfile-throws-an-outofmemoryexception-for-an-invalid-im) và đến hạn để ánh xạ các mã lỗi không được quản lý. –

+0

Nếu luồng bạn truyền tới Image.FromStream không thể tìm kiếm được, bạn có thể đóng luồng một cách an toàn. Nhưng đây là hành vi không có giấy tờ nên hãy tự chịu rủi ro. – user2452157

Trả lời

19

Lý do dòng cần phải được mở là following:

GDI +, và do đó System.Drawing namespace, có thể trì hoãn việc giải mã các bit hình ảnh thô cho đến khi bit được yêu cầu của hình ảnh . Ngoài ra, ngay cả sau khi hình ảnh đã được giải mã, GDI + có thể xác định rằng nó là hiệu quả hơn để loại bỏ bộ nhớ cho một Bitmap lớn và để giải mã sau này. Do đó, GDI + phải có quyền truy cập vào bit nguồn cho hình ảnh cho tuổi thọ của đối tượng Bitmap hoặc Hình ảnh.

Cách giải quyết ghi nhận là tạo ra hoặc là một hình ảnh không được lập chỉ mục sử dụng Graphics.DrawImage hoặc để tạo ra một chỉ mục Bitmap từ hình ảnh ban đầu như đã mô tả ở đây:

Bitmap and Image constructor dependencies

+0

Cảm ơn câu trả lời vô cùng hữu ích! Tôi biết về các tệp khóa FromFile, nhưng tôi chưa bao giờ biết lý do tại sao cho đến bây giờ. Tôi đã thử nghiệm bằng cách sử dụng phương pháp Tạo hình ảnh không được lập chỉ mục đã hoạt động tốt và ứng dụng không còn bị treo trên máy ảo XP của tôi nữa. Tôi sẽ kiểm tra lại bằng cách sử dụng cách tiếp cận được lập chỉ mục và xem điều gì xảy ra - tôi không rõ ràng về sự khác biệt giữa hai loại. –

+2

Fwiw: họ đã khắc phục một số vấn đề với định dạng pixel được lập chỉ mục trong phiên bản Vista của gdiplus.dll. Rất tốt trong số họ để làm như vậy, nhưng đau đầu khi mã của bạn cần chạy trên XP. Nói chung, tránh xa chúng để tránh rắc rối này. –

0

Bạn có thể lưu luồng vào tệp tạm thời và sử dụng phương thức Image.FromFile. Hoặc đơn giản là không nhúng hình ảnh, giữ nó như một tập tin và tải nó từ tập tin này trong thời gian chạy.

+0

Cảm ơn câu trả lời, mặc dù đây là điều tôi đã bỏ đi, như tôi biết từ kinh nghiệm trong quá khứ rằng điều này khóa tập tin do đó sẽ không thể xóa nó cho đến khi ứng dụng kết thúc. –

2

Theo tài liệu của Image.FromStream, luồng phải được giữ mở trong khi hình ảnh đang được sử dụng. Vì vậy, ngay cả khi đóng cửa làm việc (và không có gì để nói rằng bạn không thể đóng một dòng trước khi nó được xử lý, như xa như các đối tượng dòng chính nó đi) nó có thể không phải là một cách tiếp cận rất đáng tin cậy.

Bạn có thể sao chép hình ảnh sang đối tượng hình ảnh khác và sử dụng đối tượng đó. Tuy nhiên, điều này có khả năng là nhiều bộ nhớ hơn là chỉ giữ luồng mở.

+0

Cảm ơn câu trả lời. Đây là những gì tôi đã đi với, bằng cách sử dụng bài viết KB liên kết ở trên mà cung cấp những lý do tại sao. –

+0

Nó cũng chi tiết trong khi nó có thể có hiệu quả hơn để giữ lên dòng trong một số trường hợp, đó là giá trị mang trong tâm trí. –

Các vấn đề liên quan