2

如何在 WCF 双工设置中处理客户端回调方法中引发的异常?

目前,客户端似乎没有引发故障事件(除非我不正确地监视它?)但是使用客户端调用 Ping() 的任何后续操作都失败并出现 CommunicationException:“通信对象,System.ServiceModel.Channels.ServiceChannel , 不能用于通信,因为它已被中止。”。

我该如何处理并重新创建客户端等?我的第一个问题是如何找出它何时发生。其次,如何最好地处理它?

我的服务和回拨合同:

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

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

我的服务器实现:

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

        remoteMachine.Pong();
    }
}

我的客户端实现:

[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");
    }
}
4

1 回答 1

1

事实证明,您不能期望会引发 Faulted 事件。因此,重新建立连接的最佳方法是在后续调用 Ping() 失败时执行此操作:

我将在这里保持代码简单:

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...]
    //*/
}

显然,在我的示例代码中,将再次抛出异常,但我希望这有助于让人们了解如何重新建立连接。

于 2011-04-12T12:23:15.960 回答