ОБНОВЛЕНИЕ
Я объединил различные ответы отсюда в «окончательный» ответ на новый вопрос .
Оригинальный вопрос
В моем коде есть издатель событий, который существует на протяжении всего времени жизни приложения (здесь он сокращен до базовых):
public class Publisher
{
//ValueEventArgs<T> inherits from EventArgs
public event EventHandler<ValueEventArgs<bool>> EnabledChanged;
}
Поскольку этот издатель может использоваться повсеместно, я был очень доволен собой за создание этого небольшого вспомогательного класса, чтобы избежать переписывания кода обработки для всех подписчиков:
public static class Linker
{
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged += (s, e) => subscriber.Enabled = e.Value;
}
//(Non-lambda version, if you're not comfortable with lambdas)
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged +=
delegate(object sender, ValueEventArgs<bool> e)
{
subscriber.Enabled = e.Value;
};
}
}
Он работал нормально, пока мы не начали использовать его на небольших машинах, когда я начал получать случайные:
System.ComponentModel.Win32Exception
Not enough storage is available to process this command
Как оказалось, в коде есть одно место, где элементы управления подписчиками динамически создаются, добавляются и удаляются из формы. Учитывая мое глубокое понимание процесса сбора мусора и т. Д. (Т. Е. Ни одного, до вчерашнего дня), я никогда не думал о том, чтобы уйти от меня, поскольку в подавляющем большинстве случаев подписчики также живут в течение всего срока службы приложения.
Некоторое время я возился с WeakEventHandler Дастина Кэмпбелла , но он не работает с анонимными делегатами (не для меня в любом случае).
Есть ли выход из этой проблемы? Я действительно хотел бы избежать необходимости копировать и вставлять код котельной пластины по всему магазину.
(О, и не спрашивайте меня, ПОЧЕМУ мы все время создаем и уничтожаем элементы управления, это не было моим дизайнерским решением ...)
(PS: это приложение winforms, но мы обновились до VS2008 и .Net 3.5, стоит ли мне использовать шаблон Weak Event ?)
(PPS: Хороший ответ от Рори , но если кто-то может придумать эквивалент WeakEventHandler, который избавляет меня от необходимости не забывать явно UnLink / Dispose, это было бы круто ...)
РЕДАКТИРОВАТЬ Я должен признать, что обошел эту проблему, "переработав" рассматриваемые элементы управления. Однако обходной путь вернулся, чтобы преследовать меня, поскольку «ключ», который я использовал, по-видимому, не уникален (всхлип). Я только что обнаружил другие ссылки здесь (пробовал это - кажется немного слишком слабым - GC очищает делегатов, даже если цель все еще жива, та же проблема с s, oɔɯǝɹ ответьте ниже), здесь (вынуждает вас изменять издателя, и на самом деле не работает с анонимными делегатами) и здесь (цитируется Дастином Кэмпбеллом как неполное) ,
Мне приходит в голову, что то, что я ищу, может быть семантически невозможным - затворы предназначены для того, чтобы «торчать даже после моего ухода».
Я нашел другой обходной путь, поэтому я буду придерживаться этого, ожидая голоса от богов .