2010-02-26 44 views
18

GC dành cho các đối tượng được quản lý và Hoàn thành là dành cho các đối tượng không được quản lý mà tôi đã đọc. Vứt bỏ là tiềm ẩn và Finalize là rõ ràng là những gì tôi đã được đọc. Ai đó có thể cho tôi một ví dụ về một mô-đun trong đó tất cả ba điều đã được sử dụng vì các lý do khác nhau?mối quan hệ giữa GC, Finalize() và Dispose là gì?

+4

Bạn cũng có thể thêm 'Sử dụng' vào danh sách kết hợp khi đang ở đó. – RedFilter

Trả lời

25

GC là bộ sưu tập rác. Nó là quản lý bộ nhớ tự động, xử lý việc dọn dẹp các đối tượng được cấp phát trên heap được quản lý. .NET GC sử dụng một thuật toán đánh dấu và quét. Khi một bộ sưu tập rác xảy ra nó về cơ bản xem xét tất cả các đối tượng trong một phần của đống được làm sạch như là có thể phục hồi. Sau đó, nó đi qua một quá trình đánh dấu nơi nó quét rễ. I E. nó xác định các đối tượng vẫn còn được sử dụng bởi ứng dụng. Đã thực hiện rằng các đối tượng còn lại đủ điều kiện để dọn dẹp. Heap có thể được nén lại như một phần của quá trình dọn dẹp.

Phương pháp vứt bỏ và hoàn thiện cả hai đều cung cấp tùy chọn để làm sạch tài nguyên, là không phải được xử lý bởi GC. Ví dụ. điều này có thể là xử lý riêng và tương tự. Họ không có gì để làm với khai hoang bộ nhớ trên heap được quản lý.

Vứt bỏ phải được gọi rõ ràng trên loại thực hiện IDisposable. Nó có thể được gọi thông qua chính phương thức Dispose() hoặc thông qua cấu trúc using. GC sẽ không tự động gọi Dispose.

Trình hoàn thiện hoặc hủy (như đặc tả ngôn ngữ gọi nó), mặt khác sẽ tự động được gọi là đôi khi sau khi đối tượng đủ điều kiện để dọn dẹp. Các phương thức hoàn thiện được thực thi tuần tự trên một luồng chuyên dụng.

Dispose() cho phép xóa tài nguyên xác định trong khi trình kết thúc có thể hoạt động như mạng an toàn trong trường hợp người dùng không gọi Dispose().

Nếu một loại thực hiện trình kết thúc, việc dọn dẹp các phiên bản bị trễ vì trình kết thúc phải được gọi trước khi dọn dẹp. I E. nó sẽ yêu cầu một bộ sưu tập bổ sung để đòi lại bộ nhớ cho các trường hợp của loại. Nếu loại thực hiện IDisposable là tốt, phương pháp Vứt bỏ có thể được gọi và sau đó thể hiện có thể loại bỏ chính nó từ cuối cùng. Điều này sẽ cho phép các đối tượng được làm sạch như thể nó không có một finalizer.

Nếu bạn muốn tìm hiểu điều này, tôi khuyên bạn nên CLR via C# by Jeffrey Richter. Nó là một cuốn sách tuyệt vời và nó bao gồm tất cả các chi tiết đẫm máu của điều này (tôi đã để lại một số chi tiết). Phiên bản mới thứ 3 vừa được phát hành.

+1

+1, nhưng bạn có thể thêm rằng bạn có thể ngăn chặn finalizer với GC.SupressFinalize, đó là một cái gì đó bạn muốn làm nếu bạn rõ ràng vứt bỏ dụ. –

+0

Nếu Finalize được tự động gọi khi một đối tượng đủ điều kiện để dọn dẹp thì tại sao C không làm điều đó? Nếu nó là một quá trình tự động? – TeaLeave

+0

Nó không được gọi ngay lập tức. Nó được dự kiến ​​sẽ được gọi. Có thể mất một lúc trước khi nó được chạy. –

7

Bạn có thể chỉ muốn đọc những gì tôi xem xét bài viết cuối cùng về IDisposable, finalizers và thu gom rác, Shawn Farkas 'CLR Inside Out: Digging into IDisposable.

Bài viết này để lại rất ít nghi ngờ về chủ đề.

+2

Hi Mark, sự khác biệt giữa Dipose() và hai khác là những gì tôi hiểu nhưng nơi tôi đang đấu tranh là để hiểu sự khác biệt giữa Finalize() và Garbage Collector(). bởi vì có rất nhiều bài báo tôi gặp phải ở đó tác giả tôi nói rằng GC cuối cùng sử dụng Finalize() để xóa sạch các đối tượng. Sau đó, sự khác biệt giữa việc giữ Finalize() trong định nghĩa lớp và KHÔNG giữ một bởi vì mặc dù tôi không giữ Finalize() trong định nghĩa lớp, GC cuối cùng gọi Finalize() để xóa bỏ đối tượng không được sử dụng. – TeaLeave

+0

Bây giờ, một nơi nào đó tôi đọc rằng các đối tượng với Finalize() sẽ được đặt trong "Hàng đợi cuối cùng" và sau đó khi đối tượng không còn cần thiết thì bộ nhớ được thu hồi lại GC. – TeaLeave

+0

Mọi thứ có vẻ lộn xộn vì GC là USign Finalize() và Finalize đang sử dụng GC :). Tôi bối rối ......... – TeaLeave

8

Một trong những lợi ích của .NET là bộ thu gom rác. Trong nhiều ngôn ngữ, mọi bộ nhớ phải được quản lý bởi nhà phát triển - bất kỳ bộ nhớ được cấp phát nào cũng sẽ được phát hành. Trong .NET (C#), Garbage Collector (GC) sẽ xử lý quá trình giải phóng bộ nhớ cho bạn. Nó theo dõi việc sử dụng các đối tượng của bạn, và sau khi chúng trở thành "không được phát tán" (nghĩa là: không có tham chiếu nào trong ứng dụng của bạn với đối tượng đó, trực tiếp hoặc gián tiếp), bộ nhớ của đối tượng sẽ tự động được dọn sạch.

Vứt bỏ hoặc đặc biệt hơn, IDisposable và mẫu Vứt bỏ, được sử dụng để xử lý tài nguyên riêng biệt với GC. Một số tài nguyên cần phải được dọn sạch rõ ràng, vì nhiều lý do khác nhau. Điều này bao gồm việc sử dụng API "gốc" (ở đâu.NET không biết về bộ nhớ phân bổ), bằng cách sử dụng một nguồn tài nguyên mà kết thúc tốt đẹp xử lý bản địa, vv Để xử lý này sạch, bạn thực hiện IDisposable và mô hình vứt bỏ.

Hoàn thành xảy ra trên các đối tượng khi chúng sắp được thu thập bởi bộ thu gom rác. Điều này cung cấp một "mạng lưới an toàn", nơi một đối tượng cần được xử lý vẫn có thể được làm sạch, nếu sau một chút lý tưởng. Bằng cách thực hiện một finalizer, bạn có thể đảm bảo tài nguyên không được quản lý luôn được phát hành.

Vấn đề với hầu hết các mẫu là có nhiều lý do để sử dụng IDisposable và việc triển khai thích hợp khác nhau tùy thuộc vào lý do bạn đang sử dụng nó. Ví dụ, nếu bạn quấn một nguồn gốc trực tiếp, bạn nên thực hiện một finalizer, nhưng nếu bạn đóng gói một loại IDisposable khác, finalizer là không cần thiết, mặc dù bạn vẫn nên thực hiện IDisposable. Để giải quyết vấn đề này, tôi đã viết về IDisposable and finalization in depth on my blog, mô tả nhiều lý do bạn sẽ sử dụng IDisposable và các mẫu khác nhau vì các lý do khác nhau.

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