Configuring Object Lifetime

In the example used so far, no special code is used to configure the lifetime of the remote object. For a SingleCall object, no such code is required because the object is automatically destroyed at the end of each method call. For client-activated or singleton objects, however, the remote object is automatically destroyed if it is inactive for 2 minutes, provided it has been in existence for at least 5 minutes. These magic numbers are just the default properties of the lifetime lease automatically assigned to every remote object. They are encapsulated by the ILease interface in the System.Runtime.Remoting.Lifetime namespace. Table 4-2 lists the properties of the ILease interface.

Table 4-2. Lease Properties

Property

Description

CurrentLeaseTime

The amount of time remaining in the current lease, at the end of which the remote object is destroyed.

CurrentState

A value from the LeaseState enumeration. This can be Active (the lease hasn't yet expired), Expired (the lease has expired and can't be renewed), Initial (the lease has been created but isn't yet active), Null (the lease isn't initialized), or Renewing (the lease has expired and is seeking sponsorship).

InitialLeaseTime

The initial time that the object is kept in memory. This is the minimum amount of time that a remote object will live. The default is 5 minutes.

RenewOnCallTime

The minimum amount of time that the lease should be set to when the object is used. In other words, if RenewOnCallTime is 2 minutes (the default) and the CurrentLeaseTime is less than that, RenewOnCallTime is automatically increased 2 minutes every time the client invokes a remote method (or sets a remote property). This technique is known as sliding expiration and ensures that an object remains while it is being used.

SponsorshipTimeout

The amount of time that .NET waits for a lease sponsor to renew an expired lease. If no sponsor replies within this time (by default, 2 minutes), the object is destroyed.

LeaseManagerPollTime

This setting isn't provided through the ILease interface, but it is available as a configuration file setting. It determines the frequency with which the lease manager checks for expired leases. The default (10 seconds) means that the lease manager sleeps for 10 seconds after every check.

All remotable objects gain a special MarshalByRefObject.GetLifeTimeService method that returns the ILease instance currently assigned to the remote object. You can make use of this property to retrieve and examine the lease.

The next example modifies the Windows client to display information about the lease in a label control. (See Listing 4-24.) The client uses a timer and displays the current lease time in response to each timer tick. When you run the form, you'll see the lease time count down, as shown in Figure 4-11.

Listing 4-24 Tracking a lease
 Imports System.Runtime.Remoting Imports System.Runtime.Remoting.Lifetime Public Class ClientForm     Inherits System.Windows.Forms.Form     ' (Designer code omitted.)     Private RemoteObj As RemoteObjects.RemoteObject     Private Sub ClientForm_Load(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles MyBase.Load         ' Create the remote object.         RemotingConfiguration.Configure("SimpleClient.exe.config")         RemoteObj = New RemoteObjects.RemoteObject()         ' Start the timer.         tmrCheckLease.Interval = 1000         tmrCheckLease.Start()     End Sub     ' When the timer fires, retrieve all the lease information and     ' update the display.     Private Sub tmrCheckLease_Tick(ByVal sender As System.Object, _       ByVal e As System.EventArgs) Handles tmrCheckLease.Tick         Try             Dim Lease As ILease = RemoteObj.GetLifetimeService()             If Not (Lease Is Nothing) Then                 ' Display current lease information.                 lblLease.Text = "Current State: "                 lblLease.Text &= Lease.CurrentState.ToString()                 lblLease.Text &= Environment.NewLine                 lblLease.Text &= "Initial Time Allocation: " 
                 lblLease.Text &= Lease.InitialLeaseTime.ToString()                 lblLease.Text &= Environment.NewLine                 lblLease.Text &= "Time Remaining: "                 lblLease.Text &= Lease.CurrentLeaseTime.ToString()             End If         Catch err As RemotingException             lblLease.Text = err.ToString()             tmrCheckLease.Stop()         End Try     End Sub End Class 
Figure 4-11. Tracking a remote object lease

graphics/f04dp11.jpg

When the lease dips below 2 minutes, something interesting happens. Because just retrieving the lease counts as interaction with the remote object, it automatically renews the lease lifetime to 2 minutes (according to the default RenewOnCallTime). This process happens perpetually, ensuring that the object is never destroyed. You can circumvent this behavior by retrieving and storing a reference to the ILease object when your program starts. First, create the ILease reference as a form-level variable:

 Private Lease As ILease 

Then retrieve the lease in the Form.Load event:

 Private Sub ClientForm_Load(ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles MyBase.Load     ' (Other initialization code omitted.)     Lease = RemoteObj.GetLifetimeService() End Sub 

Now, even though the lease is retrieved from the remote application domain, by using a direct reference you bypass the remote object to which it applies. When you run the program, you will see the lease count down until it reaches zero, the object is deallocated, and a RemotingException is thrown.

Modifying Lifetime

You can modify an object's lifetime in several ways. From the client's point of view, you can just call a method or set a property on the remote object, which automatically returns the lifetime to the RenewOnCallTime if it has dipped below this number. However, the client can't directly modify any of the ILease properties because they are all read-only. Instead, you can use the ILease.Renew method, which accepts a TimeSpan object and updates the CurrentLeaseTime accordingly.

To test the renewal method, you can add a Renew method to the lease test client, with the event handler shown in Listing 4-25.

Listing 4-25 Renewing a lease
 Private Sub cmdRenew_Click(ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles cmdRenew.Click     ' Use the TimeSpan constructor for (Hours, Minutes, Seconds).     Lease.Renew(New TimeSpan(0, 1, 0)) End Sub 

If you click this button while the current lease time is greater than 1 minute, nothing happens. If you click this button after the lease time has dipped below 1 minute, it automatically resets the current lease time to 1 minute.

The component host can also play a hand in controlling the lifetime of the remote object. Generally, this is accomplished by setting lease defaults in the server configuration file, as shown in Listing 4-26. (These settings are case-sensitive and mirror the ILease properties, but with an initial lowercase letter.)

Listing 4-26 Configuring lifetime in the host configuration file
 <configuration>    <system.runtime.remoting>       <application name="SimpleServer">          <service>             <activated              type="RemoteObjects.RemoteObject, RemoteObjects"/> 
          </service>          <channels>             <channel ref="tcp server" port="8080" />          </channels>          <lifetime leaseTime = "10M"                    renewOnCallTime = "1M"                    sponsorshipTimeout = "0"                    leaseManagerPollTime = "30S" />       </application>    </system.runtime.remoting> </configuration> 

The lease settings apply to all the remote objects created by this component host in this application domain. Use a trailing M for minutes or an S to indicate seconds. In the preceding example, a remote object starts with an initial lifetime of 10 minutes and is renewed to 1 minute as required when the client interacts with it. By setting sponsorshipTimeOut to 0, we specify that the lease won't use any sponsors.

You can test these settings by running the lease client test. You also can try setting the leaseTime attribute to 0 minutes, which configures the remote object to have an infinite lifetime. In this case, the GetLifetimeService method returns a null reference (Nothing).

Alternatively, the remotable object can override the InitializeLiftetimeService method and take control of its own destiny. In this method, the remote object can modify the ILease properties, provided the lease hasn't yet been initialized. (See Listing 4-27.)

Listing 4-27 Overriding lease settings
 Public Overrides Function InitializeLifetimeService() As Object     Dim Lease As ILease = MyBase.InitializeLifetimeService()     ' Lease can only be configured if it is in an initial state.     If Lease.CurrentState = LeaseState.Initial Then         Lease.InitialLeaseTime = TimeSpan.FromMinutes(10)         Lease.RenewOnCallTime = TimeSpan.FromMinutes(1)     End If     Return Lease End Function 

If you want to set the object to have an infinite lifetime, you can bypass the leasing mechanism by returning a null reference, as shown in Listing 4-28.

Listing 4-28 An object with an infinite lifetime
 Public Overrides Function InitializeLifetimeService() As Object     Return Nothing End Function 

This is a common approach for a singleton object, which you often want to exist even when a client isn't using it.

Using a Leasing Sponsor

The last option is to use a leasing sponsor, which is a dedicated class that handles object renewal. When a lease manager discovers an expired lease, it first attempts to contact any registered sponsors. It then gives them the opportunity to renew the lease. This is generally better than manually renewing the lease in the client because you don't have to continuously check the current lease time. Instead, the sponsor is contacted only when necessary.

To create a sponsor, all you need is a class that implements System.Run­time.Remoting.Lifetime.ISponsor and derives from MarshalByRefObject (so that it can be called across a network). ISponsor defines a single method, called Renewal, which is called by the .NET runtime to extend the lifetime of registered objects. The class library also provides a ClientSponsor class that provides a default ISponsor implementation, complete with methods for registering and unregistering the sponsor and a RenewalTime property that sets the lease time that will be given to the remote object on renewal.

Listing 4-29 shows an example in which the lease sponsor is created in the same domain as the client application, ensuring that if the client is disconnected, the sponsor will also be unreachable (and the remote object will be destroyed). Figure 4-12 shows the arrangement.

Listing 4-29 A custom lease sponsor
 Private Sponsor As New ClientSponsor() Private Sub HostForm_Load(ByVal sender As System.Object, _   ByVal e As System.EventArgs) Handles MyBase.Load     ' Create the remote object.     RemotingConfiguration.Configure("SimpleClient.exe.config")     RemoteObj = New RemoteObjects.RemoteObject()     ' Configure and register the sponsor.     Sponsor.RenewalTime = TimeSpan.FromMinutes(5)     Sponsor.Register(RemoteObj) 
     ' Start the timer.     tmrCheckLease.Interval = 1000     tmrCheckLease.Start() End Sub 
Figure 4-12. Using a lease sponsor

graphics/f04dp12.jpg

Figure 4-12 illuminates one other detail: The lease manager needs to contact the sponsor in the client's application domain. In other words, the lease manager will act like a client, and the sponsor will act like a server. For this reason, you need to modify the configuration file to use bidirectional channels:

 <channel ref="tcp" port="0" /> 

When running the application, notice that the lease time actually dips below 0, into negative numbers. This is because the lease has expired but the lease sponsor hasn't yet been contacted. After the lease sponsor has been contacted, it responds with a renewal request and the time is reset to 5 minutes.

If necessary, the client can also retain a reference to the sponsor, which allows it to tweak the RenewalTime (for example, making it longer if the remote object is holding onto expensive server resources that could be time consuming to re-create). To switch off the sponsor, just unregister it:

 Sponsor.Unregister(RemoteObj) 

In version 1.1 of the .NET Framework, you need to explicitly allow full serialization in order to use a leasing sponsor. To do so, modify the channel portion of the client and server configuration file as shown here:

 <channels>   <channel ref="tcp" port="8080" >   <serverProviders>     <formatter ref="binary" typeFilterLevel="Full" />   </serverProviders> </channel> 

Note

Leases are efficient because they require very little network traffic. Objects that are relatively lightweight can have long lease times for convenience. Objects that require resources that are expensive to re-create might also use a longer lease time or make use of a larger RenewOnCallTime to ensure that they are always retained if they are in use. (This provides a primitive type of caching.) On the other hand, objects that encapsulate important server resources or consume a large amount of memory will generally have short lease times, ensuring that they can be released as soon as the client has finished with them. In this case, you trade increased network traffic for more efficient use of server resources.




Microsoft. NET Distributed Applications(c) Integrating XML Web Services and. NET Remoting
MicrosoftВ® .NET Distributed Applications: Integrating XML Web Services and .NET Remoting (Pro-Developer)
ISBN: 0735619336
EAN: 2147483647
Year: 2005
Pages: 174

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