14.3. Leasing and Sponsorship

 < Day Day Up > 

One of the signature features of .NET is its use of Garbage Collection to remove unused objects. As was discussed in Chapter 4, .NET maintains a graph to keep track of all references to objects in the managed heap. When Garbage Collection occurs, those objects for which references cannot be found are destroyed. Because .NET only recognizes references within a process, objects referenced by remote clients would be subject to Garbage Collection leaving the remote client(s) with no host object to call.

The rather clever .NET solution is to assign a lease object to each client-activated object or server-activated singleton when they are created. (Server-activated single call objects are not affected because they only exist for the duration of a call.) The lease provides a reference to the object that keeps the object from being made available for Garbage Collection as long as the lease exists which is based on the lease time assigned to the lease. The time associated with the lease is referred to as the object's time-to-live (TTL).

As we see next, a lease may be renewed programatically by calling methods on the lease object to increase its lease time. If the lease does expire, .NET looks for an object associated with the lease, known as a sponsor, and gives it a chance to renew the lease. Let's look at the details.


A lease is an object created internally by .NET that implements the ILease interface. This interface, located in the System.Runtime.Remoting.Lifetime namespace, defines the members that are used to govern a lease's behavior. These include properties to get or set the initial time of the lease (the default is 5 minutes), obtain the time remaining on the lease, and specify the time a lease is renewed for when its associated object is invoked. Table 14-1 summarizes the ILease members.

Table 14-1. ILease Interface Members




Amount of time remaining before the object is made available for Garbage Collection. If it is invoked, the lease time is reset.


Returns the current state of the lease, defined by a LeaseState enumeration: Active, Expired, Initial, Null, or Renewing.


Gets or sets the initial amount of time-to-live that a lease assigns to an object. Default is 5 minutes.


Gets or sets the amount of time specified using TimeSpan that a call to an object increases the CurrentLeaseTime. Default is 2 minutes.


Gets or sets the amount of time available for a sponsor to provide a new lease renewal time. Default is 2 minutes.


Registers a sponsor for the lease.


Renews a lease for a specified amount of time.


Removes a sponsor from an object's list of sponsors.

Setting Initial Lease Values for Objects in an Application

You can override the default values assigned to lease properties in an application's configuration file. For example, to set the lease values for all objects in our image server example, insert the following into the caoimagehost.exe.config file:

 <application >    <lifetime       leaseTime = "8M"       renewOnCallTime = "6M"    />    ... </application> 

In this example, the time is specified in minutes (M), but it may also be specified as days (D), hours (H), seconds (S), or milliseconds (MS).

The same effect can be achieved inside a program by setting static properties on the LifetimeServices class:

 LifetimeServices.LeaseTime = System.TimeSpan.FromMinutes(8); LifetimeServices.RenewOnCallTime =       System.TimeSpan.FromMinutes(6); 

Setting the Lease Values for an Individual Object

Both of the aforementioned techniques for setting initial lease values apply to all objects hosted by the server. To set lease values on an object-by-object basis, a different approach is required. Recall that for a class to implement remoting it must inherit the MarshalByRefObject class. This class includes an InitializeLifeTimeService method that is responsible for returning lease objects. It is a simple matter to override this method in a program to assign your own initial values to the lease object.

 using System.Runtime.Remoting.Lifetime;  // Contains ILease public class MessageManager: MarshalByRefObject, IMessageManager { // Override this method to set lease initialization values public override object InitializeLifetimeService() {    ILease msgLease = (ILease)base.InitializeLifetimeService();    msgLease.InitialLeaseTime = TimeSpan.FromMinutes(8);    msgLease.RenewOnCallTime  = TimeSpan.FromMinutes(6);    return msgLease; } 

Note that implementation of this method overrides any values in the configuration file. This means that a configuration file can be used to set default values for all objects, and this method override approach can be used to set non-default values for selected objects.

After a lease is in an active state, the only property on the lease that can be changed is its CurrentLeaseTime. This value can be renewed by a sponsor (described later) or by having the client or object explicitly invoke the lease's Renew method.

 // Client (ILease) lease=(ILease)RemotingServices.GetLifetimeServices(ob) // Object on server (ILease) lease=(ILease)RemotingServices.GetLifetimeSer- vices(this) if(lease.CurrentLeaseTime.TotalMinutes < 1.0)       lease.Renew(TimeSpan.FromMinutes(5)); 

If the current lease time is greater than this renewal time, the lease is not reset.

The Lease Manager

Running in the background of each AppDomain is a lease manager that keeps track of each server object and its associated lease. The primary function of the manager is to periodically examine the leases for time expiration and invoke a sponsor if the lease has expired.

The lease manager uses a timer to control how frequently it checks for lease expirations. By default, this is set to 10 seconds. To override the default, add this setting in the configuration file:

 <application >    <lifetime       LeaseManagerPollTime"5S"    /> 

The value can also be set programmatically using the LifetimeServices class:

 LifetimeServices.LeaseManagerPollTime =       System.TimeSpan.FromSeconds(5); 

The Lifetime of a Lease

It should be clear from the discussion thus far that a lease has a nondeterministic lifetime whose actual length is determined by calls on the associated object, direct invocation of the lease's Renew method, and any renewal coming from a lease's sponsor(s). The state diagram in Figure 14-12 illustrates the relationship between these actions and the current state of a lease. Note that a lease may be in one of four states Initial, Active, Renewing, or Expired.

Figure 14-12. Different states in which a lease may exist

When a remote object is created, .NET creates a corresponding lease and sets its InitialLeaseTime in descending order of priority to either a value set programmatically, a value in the configuration file, or a default value of 5 minutes. The lease moves into an active state, and its time begins to tick away. When a call is made on the object, the remaining lease time is compared with the renewOnCallTime value. The lease time is set to the greater of the two values. For example, if 4 minutes remain, and the renew time is 6 minutes, the value is set 6 minutes; if 7 minutes remain, the value is not altered. When the TTL value goes to 0, the lease manager checks to see if the lease has a sponsor that will assign a new lease time; if not, the object is deactivated and made available for Garbage Collection. Calls made on an object whose lease has expired throw an exception indicating that "no receiver could be found" or the "object has been disconnected." For this reason, it is important to surround all calls on a remote object with exception handling code.


A program's final opportunity to renew a lease is when the lease's CurrentLeaseTime value winds down to 0. At this point, the lease enters a LeaseState.Renewing state (see Figure 14-12), and the lease manager checks to see if any sponsor has been registered with the object (a lease may have sponsors created by multiple clients). If a sponsor is found, it is called and given the opportunity to renew the lease by returning a TimeSpan value that becomes the new TTL for the object.

This sponsorship model, based on registration and callbacks, closely resembles the .NET event handling model. In fact, a sponsor can be viewed as an event handler that is called when the lease time approaches 0. Table 14-2 spells out the similarities.

Table 14-2. Similarities Between an Event Handler and a Sponsor

Event Handler


Registers with a delegate to handle an object's event.

Registers with an object's lease when an object is created.

An event handler may be registered for multiple events.

A sponsor may register with multiple leases.

Implements a method that is called to take some action when the event occurs.

Implements a class that contains a method, Renewal, that is called when the TTL=0 event occurs. The method then takes action to extend or end the lease.

Signature of event handling method must match that of the delegate.

Renewal must always have this signature:

Timespan Renewal(ILease lease)

Although an event handler is a method, a sponsor is a class that meets two requirements: It inherits from MarshalByRefObject, and it implements the ISponsor interface:

 public class ImageSponsor: MarshalByRefObject, ISponsor 

The ISponsor interface defines only one member a method, Renewal that returns the new TTL value for the object as a TimeSpan type:

 public TimeSpan Renewal(ILease lease) 

A sponsor can be implemented on the server, client, or in a third-party assembly. The only requirement is that the lease manager can locate it. In reality, a sponsor should be defined where the application can best assess the factors that determine how or if an object's lease is extended. For an SAO singleton, this is on the server/host; for a CAO, the code should be on the client, because only the client knows how it's going to be using the object.

To demonstrate the details of implementing a sponsor, let's add one to the client code (see Listing 14-6) used in the image server example. It can be done in four steps:


Add namespaces that define an HTTP channel to be used to receive the callback from the lease manager, and the ILease and ISponsor interfaces:

 using System.Runtime.Remoting.Channels.Http; // Contains ILease and ISponsor using System.Runtime.Remoting.Lifetime; 


Register the channel to be used for the callback from the lease manager. Setting the port to 0 instructs .NET to automatically use any available port:

 // Register channel for callback from lease manager HttpChannel c2 = new HttpChannel(0); ChannelServices.RegisterChannel(c2); 

This could also be done in a client configuration file:

 <channels>    <channel ref="http" port="0"> </channels> 


Register a sponsor for the lease. First, use GetLifetimeService to get a reference to the lease. Then, pass an instance of the sponsor to the ILease.Register method:

 // Register sponsor ISponsor currSponsor = new ImageSponsor(); ILease lease =       (ILease)RemotingServices.GetLifetimeService(imgMgr); lease.Register(currSponsor); 


Define the sponsor class. It must have the proper inheritance and must provide an implementation of the ISponsor method Renewal.

 // Implement Sponsor public class ImageSponsor: MarshalByRefObject, ISponsor {    public TimeSpan Renewal(ILease lease)    {       Console.WriteLine(lease.CurrentLeaseTime);       // Set object's time to live to 10 minutes       return TimeSpan.FromMinutes(10);    } } 

In this example, the sponsor renews the lease for 10 more minutes. Because this sponsor is called each time the TTL approaches 0, the object associated with the lease exists as long as the client is running. A more sophisticated implementation would include logic that decides whether to renew the lease. To indicate no renewal, the sponsor returns TimeSpan.Zero.

Core Note

A client-based sponsor works only if the server can access the client. This technique cannot be used for a client situated behind a firewall that blocks access.

     < Day Day Up > 

    Core C# and  .NET
    Core C# and .NET
    ISBN: 131472275
    EAN: N/A
    Year: 2005
    Pages: 219

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net