2012-03-12 11 views
8

Tôi biết rằng tất cả các đối tượng thực hiện IDisposable nên được xử lý ngay sau khi chúng không còn cần thiết để giải phóng bộ nhớ được sử dụng bởi tài nguyên không được quản lý của chúng.Tôi có nên bận tâm về việc vứt bỏ các vật thể chia sẻ suốt đời của quá trình không?

Câu hỏi của tôi liên quan đến các đối tượng mà tôi biết cho thực tế sẽ hoạt động cho đến khi quá trình lưu trữ được kết thúc. Nó sẽ tạo ra bất kỳ sự khác biệt nào nếu tôi vứt bỏ chúng hay không? Có cơ hội nào của bộ nhớ không được giải phóng khi quá trình chết không? Điều gì về các đối tượng GDI? Các xử lý GDI sẽ được giải phóng khi quá trình chết ngay cả khi chúng không được xử lý?

Tôi hoàn toàn hiểu rằng thực tiễn tốt là vất bỏ mọi đối tượng. Tôi hỏi hoàn toàn tò mò.

+0

http://blogs.msdn.com/b/kimhamil/archive/2008/11/05/when-to-call-dispose.aspx Wow, mọi người đã nhảy vào tôi như một con chó trên con mèo 3 chân để nói không được vứt bỏ. Tôi đã tìm thấy nó đau hơn nó giúp. Không nên vòng đời được quản lý bởi một container, không mã cứng ??? – CrazyDart

+0

@CrazyDart Cảm ơn, đó là một đọc lặp đi lặp lại, mặc dù nó đề cập chủ yếu với câu hỏi "Nên đối tượng của loại X thường được xử lý". Câu hỏi cụ thể hơn tôi đang cố gắng trả lời là "nên đối tượng của loại X, mà nên ** chắc chắn ** bình thường được xử lý, được xử lý ngay cả khi nó chia sẻ suốt đời của quá trình?" – Rotem

+1

@CrazyDart Khi nào có Dispose làm tổn thương bạn? Liên kết mà bạn đưa ra đưa ra một số ví dụ về khi không được gọi Dispose, nhưng quy tắc chung vẫn nên gọi là trừ khi bạn có lý do chính đáng. – hvd

Trả lời

7

Tùy thuộc vào đối tượng (tài nguyên) được đề cập.

Khi quá trình chấm dứt tất cả bộ nhớ không được quản lý, tệp thủ công và các tài nguyên hệ điều hành khác sẽ được giải phóng, ngay cả khi các trình kết thúc liên quan không chạy được.

Nhưng tôi không như vậy chắc chắn về xử lý db, tên-mutexes vv

Vì vậy, trước khi bạn có thể xem xét nó an toàn để không gọi Dispose, bạn sẽ phải biết về các loại tài nguyên và làm thế nào nó liên quan đến quá trình. Dễ dàng hơn nhiều khi gọi Dispose() ra khỏi nguyên tắc chung.

Nhưng nó là một đối số lý thuyết, hầu hết các lớp sẽ sử dụng SafeHandle : CriticalFinalizerObject. Vì vậy, tôi không nghĩ rằng nó bao giờ là một vấn đề thực tế thực tế.

+0

Theo mặc định, mọi đối tượng có trình kết thúc sẽ chạy trình hoàn tất của nó. Ngược lại bạn có thể kiểm soát từ mã của bạn: 'Dispose' của bạn có thể gọi' GC.SuppressFinalize' để báo hiệu rằng finalizer không còn cần thiết nữa. (Edit: Trên thực tế, tôi nghĩ rằng mọi đối tượng không có một finalizer, nhưng theo mặc định nó không có gì.) – hvd

+1

@hvd - trong lý thuyết, một finalizer bình thường có thể được bỏ qua bởi GC. –

+0

@hvd - "Tôi nghĩ mọi đối tượng đều có trình kết thúc" đúng ", nhưng theo mặc định thì không có gì". Cũng đúng, và rất may mắn. Kết thúc thực sự là tốn kém. –

2

Không. Bằng cách thiết kế, IDisposable có sẵn để cho phép chương trình phát hành tài nguyên không được quản lý sớm, sớm hơn công cụ cuối cùng có thể thực hiện. Mà chạy vào một thời gian khá khó lường, thường là sau bất cứ khi nào một bộ sưu tập rác được thực hiện. Bạn không thể dự đoán khi điều đó xảy ra.

Không có điểm nào trong việc xử lý tại thoát chương trình, trình kết thúc được đảm bảo chạy ngay trước khi AppDomain được tải xuống và quá trình tắt.

Điều đó được cho là, có một số lạm dụng IDisposable về, mã thực tế là mong muốn bạn gọi điện. Nhưng điều đó thường dựa trên số bằng cách sử dụng câu lệnh, vì vậy, rất có thể bạn sẽ gặp phải điều đó.

+1

Trình tổng kết không được bảo đảm để chạy khi thoát chương trình. Hệ thống được đảm bảo để thực hiện một số nỗ lực để chạy chúng, nhưng điều đó không có nghĩa là chúng sẽ thực sự được thực thi. Finalizers thực sự icky, và hầu hết các đối tượng thực sự không nên có chúng. – supercat