.NET Remoting with Events in VB 2005 and .NET 2.0
September 5, 2007 at 6:31 pm 1 comment
I learned how to add events to a remote client by studying the “Chatter” remoting example in .NET Remoting and Event Handling in VB .NET, by Paul Kimmell. I will not attempt to explain the entire “Chatter” code example, since a good explanation is already given in Kimmell’s article, but I do want to point out a few important aspects that weren’t clear to me at first.
Delegate
The delegate is declared in the SharedCode project (it doesn’t really matter where it is declared, as long as it is within the scope of any class that uses it):
Public Delegate Sub MessageEventHandler(ByVal Sender As Object, ByVal e As ChatEventArgs)
Remotable class and event source
The delegate is used by the Chatter
class which is also in the SharedCode project. It appears in the event declaration of the Chatter
class:
Public Event MessageEvent As MessageEventHandler
Client class and event handler
The Chatter
class is declared in the Client
class as a private class member, FChatter
. It is instantiated by the constructor, which also adds an event handler. The event handler handles the Chatter.MessageEvent
which is of the type MessageEventHandler
. The actual address of OnMessageEvent
will be an address within the application domain of whatever application instantiates an object of type Client
. Here’s where things can get a bit confusing. The Client
class doesn’t get directly instantiated, instead this class has a shared (static) field that is given a reference to an object of it’s own type (it’s own class) when the Instance
method is called for the first time.
The most important points here, are that the Client
constructor will only be called once (this is the Singleton pattern) and will use the AddHandler
statement to add the address of the OnMessageEvent
handler to the Client object. The address will be in the application domain of the application that calls the constructor.
Private Sub New() RemotingConfiguration.Configure("client.exe.config", False) FChatter = New Chatter AddHandler FChatter.MessageEvent, AddressOf OnMessageEvent End Sub
When it is called, the delegate is given the address of the OnMessageEvent
handler in the application domain of whichever client called the Send
, or ShowHistory
method. This is important! The ClientApp
is able to receive events from the remote Chatter
object because the delegate for the event holds a reference to an event handler in the ClientApp
‘s own memory space.
Public Sub OnMessageEvent(ByVal Sender As Object, ByVal e As ChatEventArgs) If (Not IsSelf(e.Sender)) Then Broadcaster.Broadcast(Environment.NewLine) Broadcaster.Broadcast("{0} said: {1}", e.Sender, e.Message) Broadcaster.Broadcast("chat>") End If End Sub
It is also important to remember how the MarshalByRefObject
class works. The Chatter
class inherits from MarshalByRefObject
, which allows the methods of a Chatter
object to appear in a remote application domain. In other words, a remote application can instantiate a Chatter
object (which is really running in the server’s application domain) and call methods on that object. But, when the Chatter
raises an event, it will call the event handler on the client. This call goes in the opposite direction, so the client also needs to inherit from MarshalByRefObject
so that it’s event handler can be marshaled back to the Chatter
object.
Additional Reading
From dotNetJunkies
Scott Stewart, 2003, Working With Events Over Remoting
(This article is quite helpful if you can get past the non-standard grammar.)
From Useless Inc.
Tomer Gabel, 2005, Events and .NET Remoting
Entry filed under: .NET, Events, Remoting, Technology, Visual Basic. Tags: dotNET, Visual Basic.
1.
Nestor | April 7, 2010 at 1:35 pm
Hi!
There’s something I can’t understand. My client application has a reference to the shared dll, but I suppose that I cannot put a reference in the shared dll to the client application, right?
So… In the constructor of the shared class, how can I specify the name of a procedure which is in the client application (OnMessageEvent) without reference to that project?
Private Sub New
RemotingConfiguration….
FChatter = New Chatter
Addhandler FChatter.MessageEvent, AddressOf OnMessageEvent
Thank you.