6 сентября 2014 г.

Исключения при вызове метода связанного с делегатом

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

Первое что приходит в голову - сделать некий утилитарный класс и метод для работы с делегатами:


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

Тест для проверки:


Сразу было очевидно что метод DynamicInvoke будет использовать рефлексию для вызова целевого метода, что конечно отразится на производительности. Кроме рефлексии на производительность повлияет создание массива аргументов, их упаковка/распаковка при необходимости, проверка что аргументы "подходят" для целевого метода и т.д.

В качестве варианта решил передавать еще один делегат, который бы использовался для вызова целевых методов первого делегата:


Тоже самое можно сделать и для событий.

Для измерения времени выполнения использовал метод, который ничего не делает и 5 млн. его вызовов в цикле:


Результаты следующие:
  • метод Invoke - 00:00:00.0357
  • метод DynamicInvoke - 00:00:03.856
  • с использованием Action - 00:00:00.792
Считаю вариант с использованием второго делегата вполне подходящим решением.
Исходный код можно скачать здесь.

Комментариев нет:

Отправить комментарий