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

Отменить подписку на события - производительность удалась?

Рассмотрим следующий код (из отчета об эффективности):

Performance report

Это часть компонента прослушивателя свойств. Метод OnItemPropertyChanged представляет собой частный метод привязки к экземпляру с сигнатурой PropertyChangedEventHandler. Этот метод называется примерно 100 000 раз и вызывает значительные задержки в приложении.

Есть ли соображения производительности, связанные с (un) подписными событиями? Есть ли объяснение, почему это может привести к такому результату?

4b9b3361

Ответ 1

Что касается недостатка дизайна, о котором говорят многие комментарии, мы сильно убеждены в том, что пользователи не будут помещать объектный граф с 100k объектами в целом в пользовательский интерфейс; это часть непрерывного процесса совершенствования и, надеюсь, будет решена в будущем.

Не было существенной разницы между ссылкой sharedHandler и Method, передаваемой оператору отмены подписки.

Использование слабый менеджер событий устраняет поражение производительности; с или без создания таких делегатов, как Марк Гравелл. Возможно, это связано с тем, что этот класс создает свой собственный прослушиватель событий другим способом, а не использует тот, который указан в его аргументе. Я просмотрел source, но не смог найти объяснения, почему этот шаблон работает быстро (поскольку += и -= все еще вызываются).

Ответ 2

Обратите внимание, что 94.2% связано с относительным временем выполнения. Таким образом, отмена подписки занимает 94.2% от общего времени выполнения метода Disable(..). И учитывая, что другие необработанные коды кода cast и null проверяют, это нормально.

Реальная проблема, imo (даже если что-либо в отношении производительности строго зависит от конкретного контекста выполнения) заключается в том, что этот метод называется 100.000 times.

Ответ 3

Прежде всего следует отметить, что:

notificationItem.PropertyChanged -= OnItemPropertyChanged;

на самом деле выделенный новый делегат для этой цели. Это также означает, что тест эквивалентности не может быть короткозамкнутым при эквивалентности идентичности - он должен выполнять эквивалентность метода/цели (т.е. Другой экземпляр делегата, но тот же целевой/метод, поэтому считается эквивалентным для целей делегирования).

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

void OnItemPropertyChanged(object sender, PropertyChangedEventArgs args) {...}

private readonly PropertyChangedEventHandler sharedHandler;
public YourType() { // constructor
    sharedHandler = OnItemPropertyChanged;
}

Затем, когда вы подписываетесь, вместо:

notificationItem.PropertyChanged += OnItemPropertyChanged;

или

notificationItem.PropertyChanged -= OnItemPropertyChanged;

используйте вместо этого:

notificationItem.PropertyChanged += sharedHandler;

или

notificationItem.PropertyChanged -= sharedHandler;

Стоит попробовать, по крайней мере.