I am working on a system based on the publisher subscriber pattern. I have a WCF service that is running in a WPF application. There are numerous clients which connect to the service. The client side is also WPF. I am attaching code snippets of my system below:
Service:
[ServiceContract(Namespace = "http://AutoFXProfitsServer", SessionMode = SessionMode.Required, CallbackContract = typeof(ITradeMirrorClientContract))]
public interface ITradeMirror
{
[OperationContract]
string Subscribe(string userName, string password, int accountID);
[OperationContract]
bool Unsubscribe(string userName, string password, int accountID);
[OperationContract]
void PublishNewSignal(string signalInformation);
}
public interface ITradeMirrorClientContract
{
[OperationContract(IsOneWay = true)]
void NewSignal(string signalInformation);
}
public class NewSignalEventArgs : EventArgs
{
public string SignalInformation;
}
.
.
.
.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, AutomaticSessionShutdown = false)]
public class TradeMirrorService : DependencyObject, ITradeMirror
{
.
.
.
.
public string Subscribe(string userName, string password, int accountID)
{
try
{
if (AuthenticationSuccessful)
{
_callback = OperationContext.Current.GetCallbackChannel<ITradeMirrorClientContract>();
_newSignalHandler = new NewSignalEventHandler(NewSignalHandler);
NewSignalEvent -= _newSignalHandler;
NewSignalEvent += _newSignalHandler;
string suffixes = GetSuffixes();
return suffixes;
}
else
{
return "FAILED";
}
}
catch (Exception exception)
{
return "FAILED";
}
}
public bool Unsubscribe(string userName, string password, int accountID)
{
try
{
if (SearchHelper.UnAuthenticateUserCredentials(userName, password, accountID, _helper))
{
_callback = OperationContext.Current.GetCallbackChannel<ITradeMirrorClientContract>();
_newSignalHandler = new NewSignalEventHandler(NewSignalHandler);
NewSignalEvent -= _newSignalHandler;
return true;
}
else
{
return false;
}
}
catch (Exception exception)
{
return false;
}
}
public void PublishNewSignal(string signalInformation)
{
try
{
if (HeartBeatMessage())
{
}
else
{
_systemOrderID++;
signalInformation = TransformSignalInformation(signalInformation, _systemOrderID);
}
var e = new NewSignalEventArgs {SignalInformation = signalInformation};
NewSignalEvent(this, e);
}
catch (Exception exception)
{
}
}
And my app.config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding closeTimeout="23:59:59" openTimeout="23:59:59" receiveTimeout="23:59:59" sendTimeout="23:59:59" transactionFlow="false" transferMode="Buffered"
transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="1000" maxBufferPoolSize="524288" maxBufferSize="65536"
maxConnections="1000" maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<reliableSession ordered="true" inactivityTimeout="23:59:59" enabled="false"/>
<security mode="None"/>
</binding>
</netTcpBinding>
</bindings>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="false" httpGetUrl="http://95.138.188.232/autofxprofits/service"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup> </configuration>
The system works perfectly for long periods without any issues. What happens is that for some reason (about which i am not entirley sure) the service sometimes crashed with the exception:
CommunicationObjectAbortedException OR CommunicationObjectFaultedException
System.ServiceModel.CommunicationObjectAbortedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it has been Aborted.
Server stack trace:
at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen()
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at AutoFXProfitsServer.ITradeMirrorClientContract.NewSignal(String signalInformation)
at AutoFXProfitsServer.TradeMirrorService.NewSignalHandler(Object sender, NewSignalEventArgs e) in D:\Work\Trade Mirror - Kumar\AutoFXToolsTradeMirror\AutoFXProfitsServer\Service.cs:line 232
at AutoFXProfitsServer.TradeMirrorService.PublishNewSignal(String signalInformation) in D:\Work\Trade Mirror - Kumar\AutoFXToolsTradeMirror\AutoFXProfitsServer\Service.cs:line 171
OR,
System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
Server stack trace:
at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen()
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at AutoFXProfitsServer.ITradeMirrorClientContract.NewSignal(String signalInformation)
at AutoFXProfitsServer.TradeMirrorService.NewSignalHandler(Object sender, NewSignalEventArgs e) in D:\Work\Trade Mirror - Kumar\AutoFXToolsTradeMirror\AutoFXProfitsServer\Service.cs:line 235
at AutoFXProfitsServer.TradeMirrorService.NewSignalEventHandler.Invoke(Object sender, NewSignalEventArgs e)
at AutoFXProfitsServer.TradeMirrorService.PublishNewSignal(String signalInformation) in D:\Work\Trade Mirror - Kumar\AutoFXToolsTradeMirror\AutoFXProfitsServer\Service.cs:line 174
Just to reiterate, these exception occur in the PublishNewSignal method. One reason that i have made out from all the testing is that this happens when a client is abnormally closed. For example, the client process is closed from the task manager etc.
But this issue is a big pain and we can not move forawrd without fixing this stability issue. Does anyone have any idea as to why the communication object becomes faulted and the service crashes?
Hoping to get some positive feedback on this.
Thanks. Umer
Based on what you have shown it looks like you open the WCF channel (create the client) when you start the app, and then do not close it until the app closes.
There are several problems with this approach. The one that you are running into is that any disruption on the network or server will cause the channel to be unusable.
The way to do it is that everytime you need to make a WCF call you open the channel, make the call and then close the channel.
This approach gives both a more robust as well as a more scalable solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With