Do xử lý sự kiện ngăn chặn thu gom rác xảy ra?


183

Nếu tôi có đoạn mã sau:

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

PClass sẽ được thu gom rác? Hay nó sẽ quanh quẩn vẫn bắn các sự kiện của nó bất cứ khi nào chúng xảy ra? Tôi có cần phải làm như sau để cho phép thu gom rác không?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;

11
Tôi sẽ đề nghị với độc giả quan tâm đến câu hỏi này rằng có thể đáng để làm quen với các sự kiện nhẹ / mô hình sự kiện yếu, điều này KHÔNG ngăn cản việc thu gom rác xảy ra. Một bootstrap SO tốt cho chủ đề này là stackoverflow.com/questions/185931/ cấp
fostandy

20
Lưu ý cho hậu thế: đặt tham chiếu thành null chỉ đơn giản là trì hoãn trình thu gom rác bằng cách mở rộng thêm một dòng phạm vi của tham chiếu. .NET không phải là VB6.
John Saunders

Câu trả lời:


207

Đối với câu hỏi cụ thể "Sẽ pClass được thu gom rác": đăng ký sự kiện không ảnh hưởng đến bộ sưu tập pClass (với tư cách là nhà xuất bản).

Đối với GC nói chung (nói riêng, mục tiêu): nó phụ thuộc vào việc MyFunction là tĩnh hay dựa trên cá thể.

Một đại biểu (chẳng hạn như đăng ký sự kiện) cho một phương thức cá thể bao gồm một tham chiếu đến thể hiện. Vì vậy, có, một thuê bao sự kiện sẽ ngăn chặn GC. Tuy nhiên, ngay khi đối tượng xuất bản sự kiện (pClass ở trên) đủ điều kiện để thu thập, điều này không còn là vấn đề nữa.

Lưu ý rằng đây là một chiều; tức là nếu chúng ta có:

publisher.SomeEvent += target.SomeHandler;

sau đó "nhà xuất bản" sẽ giữ "mục tiêu" còn sống, nhưng "mục tiêu" sẽ không giữ "nhà xuất bản" tồn tại.

Vì vậy, không: nếu pClass sẽ được thu thập bằng mọi cách, không cần phải hủy đăng ký người nghe. Tuy nhiên, nếu pClass được tồn tại lâu dài (dài hơn ví dụ với MyFunction), sau đó pClass thể giữ dụ mà sống, vì vậy nó sẽ là cần thiết để bỏ đăng ký nếu bạn muốn mục tiêu được thu thập.

Tuy nhiên, vì các lý do tĩnh, rất nguy hiểm khi được sử dụng với các trình xử lý dựa trên cá thể.


6
Chà, nếu câu hỏi là "pClass có phải là rác được thu thập không", thì câu trả lời "nó phụ thuộc vào việc ..." có thực sự không chính xác hay không. Nó không phụ thuộc vào bất cứ điều gì, vì bản thân Marc ghi chú thêm.
Tor Haugen

@Tor - đủ công bằng - Tôi sẽ làm rõ
Marc Gravell

Mặc dù đại biểu đăng ký sự kiện chỉ chỉ một chiều, một thuê bao có ý định hủy đăng ký khỏi một sự kiện khi thực hiện với nó sẽ cần một số hình thức tham chiếu đến nhà xuất bản. Nó có thể là một WeakReference, và trong một số trường hợp có thể là một ý tưởng tốt, nhưng thường thì nó sẽ không phải là một ý tưởng mạnh mẽ.
supercat

Một câu trả lời tuyệt vời bởi vì nó cũng giải quyết nửa còn lại của câu hỏi (chưa được hỏi): nhà xuất bản sẽ ngăn người đăng ký không phải là người dùng.
Bob Sammer

Có, và như @BobSammers đã nói, Nó thực sự có thể là một vấn đề nếu một trường hợp ngắn, như Biểu mẫu / Cửa sổ, đang đăng ký một dịch vụ có tuổi thọ cao như Singleton cung cấp dữ liệu chẳng hạn: Singleton sau đó giữ tham chiếu và các đối tượng là những thứ được lưu giữ trong bộ nhớ ngay cả khi chúng ta nghĩ rằng chúng không được tải! Vì vậy, hãy rất thận trọng khi sử dụng Sự kiện. Chúng tôi đã lạm dụng các sự kiện cho phần mềm lớn của mình và rất khó để giải quyết sau đó.
Elo

9

Có, pClass sẽ được thu gom rác. Việc đăng ký sự kiện không ngụ ý rằng bất kỳ tham chiếu nào tồn tại với pClass.

Không, bạn sẽ không phải tháo bộ xử lý để pClass được thu gom rác.


8

Khoảnh khắc một phần của bộ nhớ không còn được tham chiếu nữa, nó trở thành một ứng cử viên cho bộ sưu tập rác. Khi thể hiện của lớp bạn vượt quá phạm vi, nó không còn được tham chiếu bởi chương trình của bạn nữa. Nó không còn được sử dụng và do đó có thể được thu thập một cách an toàn.

Nếu bạn không chắc chắn một thứ gì đó sẽ được thu thập, hãy tự hỏi mình câu hỏi sau: có còn tồn tại một tài liệu tham khảo nào không? Các trình xử lý sự kiện được tham chiếu bởi thể hiện đối tượng, không phải cách khác.


0

pClasssẽ được thu gom rác. Tuy nhiên, nếu đoạn mã ở trên nằm trong một lớp khác, thì thể hiện của lớp đó có thể không bị xóa nếu bạn không đặt pClassthành null.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.