Подтвердить что ты не робот

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

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

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

Edit:

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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