2010-03-28 36 views
12

Có cách nào đơn giản để lặp lại tất cả các trình xử lý đã đăng ký với một sự kiện cụ thể không? Vấn đề của tôi là khách hàng đăng ký nhưng quên hủy đăng ký để rò rỉ bộ nhớ xảy ra. Tôi cần một cách cho một đối tượng để ngắt kết nối tất cả các trình xử lý các sự kiện của nó trong phương thức Vứt bỏ để rò rỉ sẽ không xảy ra - ít nhất không phải do các sự kiện.C# Làm thế nào để hủy đăng ký tất cả các trình xử lý sự kiện từ một sự kiện cụ thể?

Trả lời

11

Set null để sự kiện của bạn: MyEvent = null;

Nhưng nó thực sự tốt hơn để làm cho khách hàng hủy đăng ký từ sự kiện của bạn.

+1

Không thể đặt sự kiện thành rỗng, bằng C#. –

+8

Thực tế là có thể, nếu bạn ở trong lớp học nơi sự kiện đã được khai báo. –

+1

Bạn chính xác. –

9

Cách tiếp cận khác là sử dụng mẫu "đại biểu yếu". Khi bạn sử dụng kỹ thuật này, sự kiện chỉ tham chiếu đến các máy khách bằng cách sử dụng WeakReference mà không giữ chúng trong bộ nhớ. Các khách hàng sẽ được thu gom rác khi chúng không còn được tham chiếu từ một phần khác của ứng dụng (và trình xử lý cũng có thể không được đăng ký tự động khi khách hàng được thu thập).

Điều này thường được sử dụng để giải quyết vấn đề với khách hàng "quên" để hủy đăng ký khỏi sự kiện .NET, do đó, có vẻ như điều này có thể rất phù hợp với sự cố của bạn.

7

Rò rỉ bộ nhớ chỉ xảy ra nếu đối tượng khác (người nghe) chết trước đối tượng của bạn (nguồn sự kiện). Trong trường hợp này, nguồn sự kiện vẫn giữ tham chiếu đến người nghe, điều này ngăn cản người nghe được thu thập. Khi nguồn sự kiện mất, người nghe chưa đăng ký cũng có thể được thu thập.

Nếu nguồn sự kiện chết trước người nghe, điều này không ngăn người nghe được thu thập sau này, khi tất cả các tham chiếu khác được đặt thành rỗng.

Điều này có nghĩa là nguồn sự kiện Phương pháp xử lý không đúng để giải quyết vấn đề này. Nó có thể được giải quyết chỉ trong một mã người nghe. Nói một cách đơn giản, bạn không thể làm gì cả, ngoại trừ việc yêu cầu khách hàng viết mã sạch.

1

Tại thời điểm viết, câu trả lời chính xác nhất là ít phổ biến nhất.

Bạn có thể vô hiệu hóa trình xử lý sự kiện nhưng điều này sẽ được zapped dù sao sau khi chủ sở hữu của nó được zapped - nó không sai để được siêu gọn gàng, nhưng như Alex nói, nó không phải là nơi vấn đề được.

Lớp nguồn của Adi sẽ cho phép thu thập các đối tượng nghe khi bản thân nó được thu thập, không có nghi ngờ gì. Vì vậy, vấn đề là đối tượng nguồn của Adi đang được mở, có thể từ một số chuỗi tham chiếu dài trong mã của khách hàng.

Bài đăng trên blog sau đây cũng xem xét một giải pháp mà Adi đang giải thích và giải thích lý do tại sao nó không cần thiết.

http://weblogs.sqlteam.com/mladenp/archive/2007/10/24/C-Care-about-Event-Memory-Leaks-with-Delegate.GetInvocationList.aspx

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