Preliminaries |
Althought I have not done so, you can copy shared assemblies to the Global Assembly Cache (GAC) which is located in %WINDOWS%\Assembly. Alternatively you can refer to the shared assembly directly in your projects.
|
Asynchronous Call Example |
Sometimes it is too costly to wait on a remote call to return. One solution may be to make the call in a seperate thread. This incurs its own cost on the client in terms of complexity and overhead. Another approach is to use the inherent asynchronous nature of delegates. Recall that a delegate is class that can be used to call a (set of) methods. The basic outline is: delegate return type delegate_name ([parameters]); Delagates have an asynchronous nature, when BeginInvoke is used on a delegate the CLR queues the call and returns to the caller immediately. The target method is subsequently called on a thread-pool thread. If a callback is specified in the BeginInvoke call, it is called when the target method returns. EndInvoke can be used to retreive any return value and in/out parameters. Here is our example.
|
// The Interface using System; namespace BaseLib { public abstract class BaseRemoteObject : MarshalByRefObject { public abstract void setValue(int pValue); public abstract int getValue(); public abstract string getText(); } } |
// The Server using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using System.Runtime.Remoting.Messaging; using System.Threading; using BaseLib; namespace Server class MyRemoteObject : BaseRemoteObject public override void setValue(int pValue) public override int getValue() public override string getText() class ServerStartup RemotingConfiguration.RegisterWellKnownServiceType( |
// The Client using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Http; using BaseLib; namespace ClientAsync SetValueDelegate svd = new SetValueDelegate(obj.setValue); GetValueDelegate gvd = new GetValueDelegate(obj.getValue); Console.WriteLine("Client begin Async calls"); int iVal = gvd.EndInvoke(arValGet); Console.WriteLine("getValue={0} getText={1}", iVal, str); DateTime end = System.DateTime.Now; |
Below is a figure of the asynchronous call. If you run the example you will see that on the server both remote methods are called without waiting implying that the client made both calls, the second call not waiting on the first to return.
|
![]() ![]() |
MultiServer Example |
A more general class of problems are handled by implementing more than one server. For example one server can be used to extract data from a database, while another server is used to format the data before passing it back to the client. This is also a very powerful technique for server load balancing. An Example:
|
// The Interface using System; namespace MultiServerLib // Implemented by the secondary server |
The common interface library consists of two abstract objects, one to be implemented by the primary server and the other by the secondary server. The secondary server takes an object that is created by the primary server as a parameter.
|
// The Primary Server using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using MultiServerLib; namespace PrimaryServer public override void setValue(int pValue) } public override int getValue() public PrimaryServer() class PrimaryServerStartup |
The primary server registers a SAO singleton.
|
// The Secondary Server using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using MultiServerLib; namespace SecondaryServer public override void doWork(BaseRemotePrimaryObject pObj) class ServerStartup |
The secondary server takes an object created on the primary server and does some work with it.
|
// The Client using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using MultiServerLib; namespace Client BaseRemotePrimaryObject brObj = (BaseRemotePrimaryObject) Activator.GetObject( BaseRemoteSecondaryObject brsObj = (BaseRemoteSecondaryObject) Activator.GetObject( brObj.setValue(910); |
The client first creates a remote primary object and a remote secondary object, then makes a remote call on the secondary object with the primary object as a parameter. When the secondary object calls a method on the primary object, no interim message is sent via the client. All messages are sent between the two server objects. Below are some figures showing the multi-server in action.
|
![]() ![]() ![]() |
Here is a diagram of what takes place.
|
![]() |
Class Factory Example |
The class factory pattern has become a well loved idiom of object-oriented design. The general idea is to generate a class indirectly, have some static method or a seperate class (the class factory) do the generating. In .Net Remoting we can use this pattern to overcome the problem of requiring a non-default constructor for a SAO. The outline is very simple:
|
// The common assembly using System; namespace FactoryLib // The factory class that generates the real class |
The worker class is the class we want to generate with a non-default constructor, (RemoteClass) the other is the class factory (RemoteFactory) used to generate the worker class instances.
|
// The Server using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using FactoryLib; namespace Server public RemoteServer(int pValue) public override int getValue() public override void setValue(int pValue) class RemoteFactoryServer : RemoteFactory public override RemoteClass NewInstance(int pInitValue) class ServerStartup RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteFactoryServer), |
The server must implement both classes, the abstract worker class (inherited by RemoteServer) and the factory class RemoteFactoryServer.
|
// The Client using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; using FactoryLib; namespace Client RemoteFactory rFact = (RemoteFactory) Activator.GetObject(typeof(RemoteFactory), RemoteClass obj1 = rFact.NewInstance(892); |
The client creates an instance of the RemoteFactory and uses it to generate a RemoteClass with a non-default constructor. Here are some shots of the class factory example.
|
![]() ![]() |
↧
.Net Remoting – Part3 Remoting Examples
↧