События в дотнете — задумка хорошая, довольно упрощает реализацию
шаблона «наблюдатель», но в ремоутинге реализованы они через одно место. Оповещения рассылаются по очереди, что уже не есть хорошо, но что гораздо хуже, так это то, что из-за умершего и не отписавшегося клиента возникает исключение где-то во внутренностях фреймворка, которые так тщательно скрываются от пользователя, из-за чего все последующие подписчики оповещения о событии не получат. Если же событие пометить атрибутом «OneWay», то ответ клиента будет проигнорирован, но умерший клиент никогда не будет удалён из списка получателей, что равнозначно утечки памяти.
MSDN считает делегаты и события небезопасными и рекомендует использовать их только при общении между процессами по каналу IPC с аутентификацией. Единственный верный способ — обратный вызов подписавшихся клиентов, но стандартных средств для упрощения данного процесса нет. Начал искать решение и наткнулся на
статью на CodeProject про события и ремоутинг. Решение в статье работает, но использует оно не стандартные каналы, а Genuine Channels из одноимённой библиотеки, которую автор предлагает у него купить. Купить, конечно, было бы проще всего, тем более у этих каналов нет многих недостатков стандартных каналов ремоутинга, но весь проект использует именно их, да и нафиг надо за стопесят баксов за лицензию.
Написал свой диспетчер событий для .Net Remoting. Клиент подписывается на события сервера, сервер добавляет клиента в список получателей и при возникновении события на сервере при помощи трэд пула рассылает события по списку всем клиентам одновременно. Умершие клиенты из списка удаляются. Клиент получает сообщение о событии на сервере и вызывает соответствующее локальное событие. Пытался вызывать метод у клиента асинхронно, но как оказалось, асинхронно метод вызывается только в случае если клиент жив. Если клиент мёртв, вызывающий трэд всё равно блокируется на время таймаута (говорят, в версии 3.0 пофиксили, но я пишу под 2.0) и последующие клиенты получают событие с задержкой. Задействовал трэд пул и синхронный вызов, благо этот паттерн в дотнете реализуется тоже элементарно, всё как по маслу. Надо бы статью на CodeProject.com написать.