2009-07-02 31 views
21

Nếu phần mềm của tôi có hai trường hợp đối tượng, một trong số đó được đăng ký với các sự kiện của người kia. Tôi có cần phải hủy đăng ký chúng với nhau trước khi chúng mồ côi để chúng được dọn dẹp bởi người thu gom rác không? Hay có lý do nào khác tại sao tôi nên xóa các mối quan hệ sự kiện? Điều gì xảy ra nếu đối tượng được đăng ký là mồ côi nhưng người đăng ký không phải là hoặc ngược lại?Tôi có cần xóa các đăng ký sự kiện khỏi các đối tượng trước khi chúng bị mồ côi không?

Trả lời

22

Có bạn đã làm. Các nhà xuất bản sự kiện đang giữ các tham chiếu đến các đối tượng và sẽ ngăn chúng khỏi bị thu gom rác.

Hãy xem ví dụ để xem điều gì xảy ra. Chúng tôi có hai lớp học; một người phơi bày một sự kiện, người khác tiêu thụ sự kiện, người kia tiêu thụ sự kiện:

class ClassA 
{ 
    public event EventHandler Test; 
    ~ClassA() 
    { 
     Console.WriteLine("A being collected"); 
    } 
} 
class ClassB 
{ 
    public ClassB(ClassA instance) 
    { 
     instance.Test += new EventHandler(instance_Test); 
    } 

    ~ClassB() 
    { 
     Console.WriteLine("B being collected"); 
    } 

    void instance_Test(object sender, EventArgs e) 
    { 
     // this space is intentionally left blank 
    } 
} 

Lưu ý cách ClassB không lưu trữ tham chiếu đến cá thể ClassA; nó chỉ đơn thuần là móc lên một trình xử lý sự kiện.

Bây giờ, hãy xem cách các đối tượng được thu thập. Trường hợp 1:

ClassB temp = new ClassB(new ClassA()); 
Console.WriteLine("Collect 1"); 
GC.Collect(); 
Console.ReadKey(); 
temp = null; 
Console.WriteLine("Collect 2"); 
GC.Collect(); 
Console.ReadKey(); 

Chúng tôi tạo một thể hiện ClassB và giữ tham chiếu đến nó thông qua biến tạm thời. Nó được thông qua một thể hiện mới của ClassA, nơi chúng tôi không lưu trữ một tham chiếu đến nó ở bất cứ nơi nào, vì vậy nó đi ra khỏi phạm vi ngay lập tức sau khi các nhà xây dựng ClassB được thực hiện. Chúng tôi có bộ thu gom rác chạy một lần khi ClassA đã đi ra khỏi phạm vi, và một khi ClassB đã đi ra khỏi phạm vi. Kết quả:

Collect 1 
A being collected 
Collect 2 
B being collected 

Kịch bản 2:

ClassA temp = new ClassA(); 
ClassB temp2 = new ClassB(temp); 
temp2 = null; 
Console.WriteLine("Collect 1"); 
GC.Collect(); 
Console.ReadKey(); 
temp = null; 
Console.WriteLine("Collect 2"); 
GC.Collect(); 
Console.ReadKey(); 

Một ví dụ mới của ClassA được tạo ra và một tham chiếu đến nó được lưu trữ trong biến temp. Sau đó, một thể hiện mới của ClassB được tạo ra, nhận được cá thể ClassA trong temp được truyền cho nó, và chúng ta lưu trữ một tham chiếu đến nó trong temp2. Sau đó, chúng ta thiết lập temp2 thành null, làm cho cá thể ClassB thoát khỏi phạm vi. Như trước đây, chúng tôi có bộ thu gom rác chạy sau mỗi trường hợp đã hết phạm vi. Đầu ra:

Collect 1 
Collect 2 
B being collected 
A being collected 

Vì vậy, để kết luận; nếu cá thể cho thấy một sự kiện diễn ra ngoài phạm vi, nó sẽ có sẵn để thu thập rác, bất kể có xử lý sự kiện hay không. Nếu một cá thể có một trình xử lý sự kiện nối với một sự kiện trong một cá thể khác, nó sẽ không sẵn sàng cho việc thu gom rác cho đến khi trình xử lý sự kiện được tách ra, hoặc cá thể mà trình xử lý sự kiện được đính kèm sẵn sàng cho việc thu gom rác.

9

Bạn chỉ cần mở móc ra sự kiện nếu đối tượng lộ các sự kiện là tồn tại lâu dài, nhưng đối tượng hooking sự kiện này nếu không sẽ là ngắn ngủi (và được thu gom rác thải khá nhanh chóng).

Trong trường hợp này, không hủy bỏ sẽ gây ra những gì số tiền bị rò rỉ bộ nhớ, vì đối tượng sống ngắn của bạn sẽ không thể được GCed - vì sự kiện trong đối tượng tồn tại lâu dài giữ trên một đại biểu, giữ một tham chiếu đến đối tượng sống ngắn. Vì đối tượng sống ngắn này vẫn được tham chiếu bởi đại biểu đó, nó không thể lấy rác.

Sự kiện tĩnh tồn tại lâu dài theo định nghĩa - chúng tồn tại cho đến khi chương trình thoát. Nếu bạn móc một sự kiện tĩnh, bạn chắc chắn sẽ bỏ qua nó khi bạn hoàn thành.

Nếu cả hai đối tượng sắp bị mồ côi, bạn không cần phải tìm thiết bị.

5

Đăng ký kết quả sự kiện có liên quan chặt chẽ đến người đăng ký. Điều này là bởi vì, dưới sự bao gồm, các sự kiện là các đại biểu, và các đại biểu cho các phương thức ví dụ là một sự kết hợp của tham chiếu đối tượng và phương thức thực tế. Nếu bạn không hủy đăng ký, nhà xuất bản sẽ tiếp tục duy trì tài liệu tham khảo và các đối tượng đăng ký không bao giờ thực sự mồ côi (và GC'ed) miễn là nhà xuất bản vẫn còn hoạt động.

Điều ngược lại không đúng nghĩa là đối tượng đã đăng ký không có bất kỳ tham chiếu nào đến nhà xuất bản.

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