Hi all.
This case was tried in VC++.NET.
I subscribe a .NET event from a remote client app (just
add it up to the event delegator).
My server app fires the event and everything goes well
across the network.
Now imagine the client app suddenly goes down (either the
app misbehaves or the client computer crashes).
From then on, every time the event is fired, I get an
exception. Worse than that is the fact that every other
client that subscribed the event after the misbehaving
client doesn't catch the event as it will never be fired
to them.
How can I prevent this from happening, namely making sure
every client gets the event if one of them throws an
exception? Can I unsubscribe the bad client from the
event?
Thanks for your help in advance,
André Baptista
Mark Belles - 09 Sep 2003 14:51 GMT
This is a common problem with remote events. If one
client has problems, then all clients that subscribed
after the client is going to get ignored. What you can do
is manually call each client and wrap the call with a try
catch to prevent it from throwing an exception and
bailing on each sequential client. Here is some C# code
taht I use for my remoted events.
I have a server activated object that implements a shell
hook on a station and provides window events via
remoting. So here is the code for how I fire my events
from the server to the clients. Forgive the formatting if
it is screwy.
To explain the code, just take your event, and call the
Delegate's GetInvocationList() to return a delegate[]
which you can then loop thru and call each delegate
manually, if an exception occurs you can then remove the
client from the list. I've had good luck using this
method, maybe it can help you too.
/// <summary>
/// Raises the WindowActivated event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected override void OnWindowActivated
(object sender,
DEPCO.ComputerManagement.Common.WindowEventArgs e)
{
try
{
// get the invocation
list of subscribers to be notified
System.Delegate[]
invocationList = this.WindowActivated.GetInvocationList();
// loop thru the list and
try and notify each one
foreach(System.Delegate
subscriber in invocationList)
{
try
{
// cast
the delegate back to our type of delegate
DEPCO.ComputerManagement.Common.WindowEventHandler
callback = (
DEPCO.ComputerManagement.Common.WindowEventHandler)
subscriber;
//
publish the event to the subscriber using the callback
delegate
callback
(sender, e);
}
catch(Exception
deadClientException)
{
// the
subscriber is a dead client and will be removed from the
chain
this.WindowActivated -=
(DEPCO.ComputerManagement.Common.WindowEventHandler)
subscriber;
//
System.Delegate.Remove(eventDelegate, subscriber);
System.Diagnostics.Trace.WriteLine
(deadClientException.Message);
}
}
}
catch(NullReferenceException /*
nullReferenceException */)
{
// No clients have
subscribed to this event
}
}