WCF Duplex: How to handle thrown exception in duplex Callback
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();开发者_JAVA技巧
}
}
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");
}
}
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.
精彩评论