Слабая ссылка и обработка событий - PullRequest
31 голосов
/ 09 октября 2008

Является ли хорошей практикой реализация обработки событий через WeakReference, если это событие является единственной вещью, содержащей ссылку, и что нам нужен объект для сборки мусора?

В качестве аргумента этому:

Люди говорят, что если вы подписываетесь на что-то, вы обязаны отказаться от подписки, и вы должны это сделать.

Ответы [ 4 ]

14 голосов
/ 09 октября 2008

Хорошо, когда есть возможность отказаться от подписки на события, но иногда не существует очевидного метода «очистки», в котором это можно сделать. Недавно мы опубликовали статью блога на эту тему; он включает методы, облегчающие подписку на событие с помощью WeakReference.

9 голосов
/ 09 октября 2008

Слабый шаблон делегата - это то, что должно быть в CLR. Нормальные события демонстрируют семантику «уведомь меня, пока ты жив», в то время как часто нам нужно «уведомить меня, пока я жив». Просто иметь делегат на WeakReference неправильно, потому что делегат - это тоже объект, и даже когда получатель еще жив и имеет входящие ссылки, на сам делегат ссылается только упомянутый WeakReference, и он будет собран немедленно. См. этот старый пост для примера реализации.

6 голосов
/ 09 октября 2008

Слабые ссылки сами по себе, не решают проблему, поскольку делегат держит ссылку. В библиотеке составных приложений, поставляемой с Prism (www.microsoft.com/compositewpf), есть класс WeakDelegate, который можно извлечь из источника. WeakDelegate в основном использует рефлексию и создает делегата только на мгновение, а затем освобождает его, тем самым не удерживая никаких указателей. В CAL он используется классом EventAggregator, но вы можете свободно использовать его для собственного использования, как в MS-PL.

0 голосов
/ 09 октября 2008

Хотя то, что вы предлагаете, решает один набор проблем (управление ссылками на события и предотвращение утечек памяти), оно может открыть новый набор проблем.

Одна проблема, которую я вижу в процессе обработки событий, если исходный объект является сборщиком мусора (поскольку он содержался только со слабой ссылкой), любой код, который обращается к исходному объекту, приведет к исключению нулевой ссылки. Вы можете утверждать, что обработчик событий либо не должен обращаться к исходному объекту, либо он должен иметь надежную ссылку, но можно утверждать, что это может быть хуже, чем та, которую вы пытаетесь решить в первую очередь.

...