Постоянные подписчики

При разработке сервисов для небольшой программы вы, скорее всего, не думаете о многопоточности, о том, что какой-либо метод сервиса будут запускать сразу несколько экземпляров класса и много еще о чем обычно не думаете. Так же как и я. В небольших программах, которые, скорее всего, будут исполняться в один поток, не надо развитой системы событий. Можно просто передать делегат, который будет вызван после окончания работы сервиса.

Может быть обстоятельства, а может быть что-то уложилось в голове, но описанный выше подход больше не работает в программах, которые я пишу. Слишком много действий одновременно может делать пользователь и начинка программы, чтобы оставаться в рамках модели «один сервис – один потребитель». Однако с новым подходом меняется сложность и ответственность кода, и на этом пути поджидают многие сложности и опасности.

Новый подход, как вы наверно догадались, будет состоять в построении системы на событиях (event). При первом взгляде не видно никаких проблем при использовании событий, но это только на первый взгляд. Не уверен, что можно правильно проранжировать опасности, но, пожалуй, перечислю их в той последовательности, в которой с ними сталкиваешься.

Повторно подписались. Самая частая ошибка, которая вводит в ступор людей, это когда они обнаруживают:

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

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

Забыли отписаться. Бывает так, что повторной подписки не происходит, но и отписаться от события забыли. В этом случае могут возникнуть утечки памяти, так как сервис держит класс и не дает сборщику мусора пометить объект на удаление.

К слову, не всегда бывает удобно отписываться и хочется, чтобы подписка была «слабой», как WeakReference. Тогда, если на объект нет внешних ссылок, кроме слабых подписок, то сборщик мусора пометит его на удаление, подписка освободится, память освободится и будет небольшое программистское счастье. Собственно, об этом и пойдет речь, как реализовать и использовать в своем приложении слабую подписку на события. Попутно я планирую раскрыть еще несколько рабочих моментов при использовании событий и сервисов.

Подробнее