Спонсоры лизинга сервера (и клиента)
Спонсоры лизинга сервера (и клиента)
Заключительной темой нашего связанного с лизингом обсуждения цикла существования САО-типов и WKO-синглетов будет спонсорство лизинга. Как вы только что убедились, для каждого объекта САО-типа и WKO-синглета имеются параметры лизинга, используемые по умолчанию, которые можно изменить несколькими способами, как на стороне сервера, так и на стороне клиента. Но, независимо от конфигурации лизинга типа, в конечном итоге время лизинга MBR-объекта истечет. В этот момент среда выполнения отправит данный объект в "мусорник"… ну, хорошо, почти отправит.
Суть в том, что перед тем, как пометить ненужный тип для отправки сборщику мусора, среда выполнения проверяет, не имеет ли данный MBR-объект зарегистрированных спонсоров лизинга. Простыми словами, спонсор – это тип, реализующий интерфейс ISponsor, который определен так, как показано ниже.
public interface System.Runtime.Remoting.Lifetime.ISponsor {
TimeSpan Renewal(ILease lease);
}
Если среда выполнения обнаружит, что у MBR-объекта имеется спонсор, этот объект не будет сразу же отправлен сборщику мусора, а будет вызван метод Renewal() объекта спонсора, чтобы (еще раз) добавить время к текущему времени лизинга. С другой стороны, если окажется, что для данного MBR-типа спонсора нет, цикл существования объекта действительно закончится.
Предположим, что вы создали пользовательский класс, реализующий ISponsor и вызывающий метод Renewal() для возврата конкретной величины времени (через тип TimeSpan). Тогда как ассоциировать указанный тип с данным удаленным объектом? И снова это может быть сделано либо доменом приложения сервера, либо доменом приложения клиента.
Для этого заинтересованная сторона должна получить ссылку ILease (с помощью наследуемого метода GetLifetimeService() на стороне сервера или статического метода RemotingServices.GetLifetimeService() на стороне клиента) и вызвать Register().
// Регистрация спонсора на стороне сервера.
CarSponsor mySponsor = new CarSponsor();
ILease itfLeaseInfo = (ILease)this.GetLifetimeService();
itfLeaseInfo.Register(mySponsor);
// Регистрация спонсора на стороне клиента.
CarSponsor mySponsor = new CarSponsor();
CarProvider cp = new CarProvider(cars);
ILease itfLeaseInfo = (ILease)Remoting.Services.GetLifetimeService(cp);
itfLeaseInfo.Register.(mySponsor);
В любом случае, если клиент или сервер желают отменить спонсорство, это можно сделать с помощью метода ILease.Unregister(), например:
// Отключение спонсора для данного объекта.
itfLeaseInfo.Unregister(mySponsor);
Замечание. Объекты клиента, имеющие спонсоры, кроме необходимости реализации ISponsor должны быть производными от MarshalByRefObject, поскольку клиент должен передать спонсор в удаленный домен приложения.
Как видите, управление циклом существования MBR-типов, кумулятивно изменяющих параметры своего состояния в процессе выполнения вызовов клиентов, оказывается немного более сложным, чем простая сборка мусора. На стороне преимуществ мы имеем широкие возможности управления относительно того, когда именно следует уничтожить удаленный тип. С другой стороны, существует вероятность того, что удаленный тип будет уничтожен без ведома клиента. Если клиент попытается вызвать члены типа, уже удаленного из памяти, среда выполнения сгенерирует исключение System.Runtime.Remoting.RemotingException, и в этот момент клиент может либо создать новый экземпляр удаленного типа, либо выполнить другие предусмотренные для такого случая действия.
Исходный код. Проекты CAOCarGeneralAsmLease, CAOCarProviderServerLease и CAOCarProviderClientLease размещены в подкаталоге, соответствующем главе 18.