WCF Duplex: How to handle thrown exception in duplex Callback

北战南征 提交于 2019-12-11 03:13:59

问题


How do I handle an exception thrown in a callback method on the client in a WCF duplex setup?

Currently, the client does not appear to raise the faulted event (unless I'm monitoring it incorrectly?) but any subsequent to call Ping() using the the client fails with CommunicationException: "The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it has been Aborted.".

How do I deal with this and recreate the client etc? My first question is how to find out when it happens. Secondly, how best to deal with it?

My service and callback contracts:

[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
public interface IService
{
    [OperationContract]
    bool Ping();
}

public interface ICallback
{
    [OperationContract(IsOneWay = true)]
    void Pong();
}

My server implementation:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Single)]
public class Service : IService
{
    public bool Ping()
    {
        var remoteMachine = OperationContext.Current.GetCallbackChannel<ICallback>();

        remoteMachine.Pong();
    }
}

My client implementation:

[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Single)]
public class Client : ICallback
{
    public Client ()
    {
        var context = new InstanceContext(this);
        var proxy = new WcfDuplexProxy<IApplicationService>(context);

        (proxy as ICommunicationObject).Faulted += new EventHandler(proxy_Faulted);

        //First Ping will call the Pong callback. The exception is thrown
        proxy.ServiceChannel.Ping();
        //Second Ping call fails as the client is in Aborted state
        try
        {
            proxy.ServiceChannel.Ping();
        }
        catch (Exception)
        {
            //CommunicationException here 
            throw;
        }
    }
    void Pong()
    {
        throw new Exception();
    }

    //These event handlers never get called
    void proxy_Faulted(object sender, EventArgs e)
    {
        Console.WriteLine("client faulted proxy_Faulted");
    }
}

回答1:


As it turns out, you cannot expect the Faulted event to be raised. So, the best way to re-establish the connection is to do it when the subsequent call to Ping() fails:

I'll keep the code simple here:

public class Client : ICallback
{
    public Client ()
    {
        var context = new InstanceContext(this);
        var proxy = new WcfDuplexProxy<IApplicationService>(context);

        (proxy.ServiceChannel as ICommunicationObject).Faulted +=new EventHandler(ServiceChannel_Faulted);

        //First Ping will call the Pong callback. The exception is thrown
        proxy.ServiceChannel.Ping();
        //Second Ping call fails as the client is in Aborted state
        try
        {
            proxy.ServiceChannel.Ping();
        }
        catch (Exception)
        {
            //Re-establish the connection and try again
            proxy.Abort();
            proxy = new WcfDuplexProxy<IApplicationService>(context);
            proxy.ServiceChannel.Ping();
        }
    }
    /*
    [...The rest of the code is the same...]
    //*/
}

Obviously, in my example code, the Exception will be thrown again but I hope this is useful to give people an idea of how to re-establish the connection.



来源:https://stackoverflow.com/questions/5579540/wcf-duplex-how-to-handle-thrown-exception-in-duplex-callback

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!