简体   繁体   中英

.NET Remoting: How to handle disconnected objects

First, let me explain a little bit about my setup. My server is setup as a Marshaled singleton object:

 RemotingServices.Marshal(lsServer, ServerObject.objectUri);

In order to have two-way communication from the server to the client, the client activates a ServerObject, then passes in its own ClientObject (which is also a MarshalByRefObject) the server uses the ClientObject to talk back to the client:

var lsClient = new ClientObject();

var lsServer = (ServerObject)Activator.GetObject(typeof(ServerObject), url);
lsServer.attach(lsClient);

When the attach method is called, the server takes the ClientObject and stores it in a List:

public void attach(ClientObject client) {
    clientList.Add(client);
}

The server can then call a method on the ClientObject called "SendMessage" to communicate to each client in its list:

foreach(var c in clientList) {
    c.SendMessage("Hello");
}

This works great until a client is encountered that has disconnected. In this case, an error is thrown about the client refusing the connection. I can catch the error, but the problem is I cannot remove the reference to the ClientObject from the server's List. The following re-throws the "connection refused" exception anytime a client has been disconnected:

clientList.Remove(badClient);

So a couple of questions:

1- Is there a way to detect the connection state of a client without having to catch an error?

2- When I do detect a client that has disconnected, why does the attempt to remove the object from the server's list appear to "communicate" with the client (thus causing the exception to be thrown again?)

EDIT

As Patrick pointed out below, doing a Remove from a list causes the List to iterate my objects and do a comparison on them (calling .Equals) - this is what caused my ClientObject to attempt to communicate again and thus throw the exception.

To resolve it, I instead changed the List to a dictionary keyed off a unique ID supplied by my Client at the time of attaching to the server. Then I used that unique ID to remove the client.

I never did find a direct way for determining if a client had disconnected other than catching the error.

Not sure on #2. However, if you're trying to remove an item from clientList from inside the foreach loop, you can't. That's a .NET rule -- no changing the contents of an enumerable object while it's being enumerated.

Instead, if you catch the error inside the foreach loop, store it in another list (a "disconnected" list). After the foreach, remove all of the disconnected items from the clientList .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM