2012-10-11 39 views
7

Tôi đã có ý tưởng này trong khi suy nghĩ về cách tái chế các đối tượng. Tôi đang làm điều này như là một thử nghiệm để xem làm thế nào bộ nhớ tổng hợp hoạt động và tôi nhận ra rằng trong 99% kịch bản này là rất không cần thiết.Giữ đối tượng trên nỗ lực phá hủy GC

Tuy nhiên, tôi có một câu hỏi. Có cách nào để buộc GC giữ đối tượng không? Nói cách khác, tôi có thể yêu cầu GC không phá hủy một đối tượng và nói thay vào đó có tham chiếu mới được tạo trong danh sách có sẵn để sử dụng các đối tượng không? Vấn đề này, mặc dù tôi đã không kiểm tra này, là nếu tôi thêm một cái gì đó như thế này vào một danh sách:

~myObject() 
{ 
    ((List<myObject>)HttpContext.Current.Items[typeof(T).ToString()]).add(this);//Lets assume this is ASP 
} 

nó sẽ thêm một con trỏ đến đối tượng này vào danh sách, nhưng nếu đối tượng bị phá hủy tôi sẽ nhận được một ngoại lệ con trỏ null vì đối tượng không còn ở đó nữa. Tuy nhiên, có lẽ tôi có thể nói cho GC không thu thập vật phẩm này và do đó giữ vật thể?

Tôi biết đây là loại nội dung mà hầu hết các lập trình viên sẽ đi "tại sao bạn lại làm điều này?". Nhưng mặt khác, lập trình là về việc thử mới và học những điều mới. Bất kỳ đề xuất, suy nghĩ, triển khai? Mọi sự trợ giúp sẽ rất được trân trọng!

Trả lời

6

Vâng, điều này là hợp pháp. Nó được gọi là 'phục sinh'. Khi bạn chỉ định tham chiếu this đến một nơi nào đó là 'hoạt động', thì đối tượng không còn được coi là rác.

Bạn cũng sẽ cần đăng ký lại để hoàn tất sử dụng GC.ReRegisterForFinalize(this) hoặc lần tiếp theo đối tượng trở thành rác, nó sẽ không được hoàn thành (trình hủy sẽ không được gọi).

Bạn có thể đọc thêm về sự phục sinh đối tượng trong this MSDN Magazine article.

0

GC sẽ chỉ quản lý các đối tượng có tham chiếu biến mất nếu đi ra khỏi phạm vi được giải phóng một cách rõ ràng.

Dù bằng cách nào bạn cũng sẽ muốn xem các phương pháp KeepAliveSuppressFinalize để ngăn không cho GC thu gom rác từ vật thể của bạn. Một khi bạn đang thực sự thực hiện với họ, bạn sẽ cần phải đăng ký chúng để được chọn bởi các nhà sưu tập sử dụng ReRegisterForFinalize.

+0

SuppressFinalize chỉ hủy bỏ chạy trình hủy, chứ không phải bộ sưu tập. KeepAlive tốt hơn nhưng bạn phải gọi nó ở đâu đó, không thực tế. –

2

Có, điều này là có thể và thậm chí có tên: phục sinh.

nhưng nếu đối tượng bị hủy, tôi sẽ nhận được ngoại lệ con trỏ rỗng vì đối tượng không còn ở đó nữa.

Tệ hơn nhiều, bạn sẽ gặp lỗi con trỏ (tham chiếu) không hợp lệ. Và có thể là màn hình màu xanh hoặc máy chủ bị lỗi. Nhưng may mắn là CLR sẽ không để điều đó xảy ra. Đơn giản chỉ cần đặt một trường hợp phải chịu số phận trong bất kỳ loại danh sách nào làm cho nó có thể truy cập được và sau đó nó sẽ không được khai hoang.

Khi bạn muốn đối tượng của mình được tái chế nhiều lần, bạn sẽ phải gọi GC.ReRegisterForFinalize(x) trên đó.

Câu trả lời thực tế nhất mặc dù: đừng làm điều đó. Các destructor một mình chiếm chi phí đáng kể và có rất nhiều cách để có được điều này sai.

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