防止WCF回调中的异常

时间:2010-02-25 08:14:21

标签: c# wcf exception callback chat

我正在制作一个小型聊天应用程序。我到了一个客户端发送消息,然后通过使用房间中其他客户端的回调,他们很快收到消息。因此,如果房间里有10个人,发送消息的客户端的服务实例将在10个线程中调用它:

targetCallback.RecieveMessage(message);

现在,互联网连接是不稳定的,它可能恰好在执行之前打破了一段时间,因此会抛出异常并且客户端实例会自动销毁,从而使消息保持未发送或半成功。

我找到的例子根本没有真正处理这些例外,而其他例子则很简单:

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

但是,这是处理此异常的最佳方法吗?

2 个答案:

答案 0 :(得分:3)

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

获得好的建议。简而言之,您应该捕获TimeoutException和CommunicationException。

答案 1 :(得分:2)

我在调用WCF回调时也看到过ObjectDisposedExceptions,也许是某种类型的SecurityException,但我记不起哪一个了。

对于需要更高可靠性的应用程序,我编写了一个基本的包装器方法,它捕获所有异常并从回调集合中删除该回调。然后我只通过包装器调用回调。

通常我还会从OperationContext中捕获一些有关连接的上下文信息,比如IP地址,sessionID和用户令牌,这样我就可以识别出失败并记录下来。但这仍然是读者的一种练习。

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;
        {
    }

}