Как узнать, что подписано на событие в C#?

У меня проблема, когда приложение, над которым я работаю, имеет утечки памяти. Опыт научил меня, что одним из первых мест утечки памяти в языках, собранных мусором, является подписка на события и неспособность отменить их позже. Второе связано с сохранением статического состояния. Я новичок в C# и был разочарован непрозрачным типом события.

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

Edit:

Спасибо за указатель на GetInvocationList() метод. Я пытаюсь создать отладочный жгут, который будет динамически сбрасывать результаты. Проблема в том, что решения, которые я нашел, работали в .Net 2, но больше не в .Net 3.5. По сути, вы должны получить соответствующий FieldInfo для EventInfo (reflection, GetField и GetEvents соответственно). Однако в .Net 3.5 нет соответствующего FieldInfo, и EventInfo не позволит мне получить список вызовов.

Я просто хочу сбросить список событий и их InvocationList для целей отладки.

3 ответов


попробуйте использовать метод event под названием GetInvocationList.

это вернет массив делегатов, подписывающихся на событие.

массив будет содержать делегатов в том порядке, в котором они были добавлены. Это также можно использовать для выделения и вызова определенных делегатов из списка, вызывая event.Invoke метод вызовет их все (но только даст вам возвращаемое значение последнего вызываемого делегата)


вы, безусловно, правы, подозревая подписку на событие как причину утечек памяти."Несколько лет назад мы отследили проблему, когда статический объект приложения подписывался на ASP.NET страница события-вы можете догадаться, что там произошло.

другой способ решить эту проблему-с точки зрения издателя. Это может быть не удобно, чтобы получить все ваши подписчики отказаться от подписки, но если издатель должен быть уничтожен/выйти из области, возможно, он может быть запущен, чтобы установить все его события для null-эффективно отменяют подписку на всех и разрывают циклы.

Если издатель имеет более длительный срок службы и является вещью, поддерживающей другие объекты, вам, возможно, придется сделать вещь GetInvocationList, предложенную ранее. Но я бы рассмотрел это только для отладки проблемы-выяснения того, кто цепляется за события, когда они не должны.

в крайнем случае вы можете рассмотреть какой-то механизм подписки на пользовательские события на основе WeakReferenced.


посмотреть этот блог для изящный способ увидеть полезные дамп нигде событием в окно смотреть.