简体   繁体   中英

Prevent Exceptions From WCF Callbacks

I'm making a small chat application. I got to the point where one client sends a message, and then by using callbacks of other clients in the room, they quickly recieve the message. So, if there are 10 people in the room, the service instance of the client who is sending the message, will invoke this in 10 threads:

targetCallback.RecieveMessage(message);

Now, internet connections are volatile, and it could just so happen that it breaks a moment before that's performed, so an exception would be thrown and the client instance automatically destroyed, leaving the message unsent or half-successful.

I found examples that don't really handle those exceptions at all, while other put a simple:

try
{
    targetCallback.RecieveMessage(message);
}
catch
{
}

But, is that the best way to handle this exception?

See

http://msdn.microsoft.com/en-us/library/aa354510.aspx

for good advice. Briefly, you should catch TimeoutException and CommunicationException.

I've also seen ObjectDisposedExceptions when calling WCF callbacks, and maybe a SecurityException of some sort, but I can't remember which one.

For applications that need a higher degree of reliability, I write a basic wrapper method that catches all the exceptions and removes that callback from your callback collection. Then I only ever invoke the callback through the wrapper.

Normally I'd also capture some contextual information about the conneciton from the OperationContext like IP address, sessionID and user token so I can identify who failed and log it. But that's left as an exercise to the reader.

public interface ICallbackContract
{
    void Operation(string arg);
}

class Program
{
    private List<ICallbackContract> Callbacks;

    private void SendMessage(string msg)
    {
        lock (this.Callbacks)
        {
            foreach (var callback in this.Callbacks)
            {
                this.InvokeWcf(callback, (c) => c.Operation(msg));
            }
        }
    }

    public void InvokeWcf(this ICallbackContract contract, Action<ICallbackContract> op)
    {
        if (((ICommunicationObject)contract).State != CommunicationState.Opened)
        {
            lock (this.Callbacks)
                Callbacks.Remove(contract);
            myLogger.LogError("That contract isn't open! Disconnected.");
            return;
        }

        try
        {
            op(contract);
        }
        catch (TimeoutException ex)
        {
            lock (this.Callbacks)
                Callbacks.Remove(contract);
            myLogger.LogError("That contract timed out! Disconnected.", ex);
            return;
        }
        catch (CommunicationException ex)
        {
            ...
        }
        catch (ObjectDisposedException ex)
        {
            ...
        }
        catch (Exception ex)
        }
            // Unexpected case.
            lock (this.Callbacks)
                Callbacks.Remove(contract);
            myLogger.FatalError("Something really bad happened!.", ex);
            throw;
        {
    }

}

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