CommunicationObjectAbortedException& WCF服务中的CommunicationObjectFaultedException

时间:2013-01-21 16:49:20

标签: wpf wcf exception service

我正在开发一个基于发布者订阅者模式的系统。我有一个在WPF应用程序中运行的WCF服务。有许多客户端连接到该服务。客户端也是WPF。我正在附上我的系统的代码片段:

服务

[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)
        {
        }
    }

我的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>

系统可以长时间正常运行而不会出现任何问题。发生的事情是由于某种原因(我不确定),服务有时会因例外而崩溃:

CommunicationObjectAbortedException或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

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

重申一下,这些异常发生在PublishNewSignal方法中。我从所有测试中得出的一个原因是,当客户端异常关闭时会发生这种情况。例如,客户端进程从任务管理器等关闭。

但是这个问题是一个巨大的痛苦,如果不解决这个稳定性问题我们就无法移动。有没有人知道为什么通信对象出现故障并且服务崩溃了?

希望得到一些积极的反馈。

感谢。 乌默尔

2 个答案:

答案 0 :(得分:8)

经过一番研究,我自己解决了这个问题。问题是每当我的客户端在没有正确取消订阅的情况下意外断开连接,并且服务没有正确处理丢弃的客户端。因此,通信对象出了问题。 Lee'sthis question的回答确实帮助我思考了正确的方向。经过一些研究,我发现this discussion在解决问题时非常有用。

答案 1 :(得分:1)

根据您显示的内容,您似乎在启动应用时打开WCF频道(创建客户端),然后在应用关闭之前不要关闭它。

这种方法存在一些问题。您遇到的问题是网络或服务器上的任何中断都会导致通道无法使用。

这样做的方法是,每当你需要拨打WCF电话时,你打开频道,拨打电话,然后关闭频道。

这种方法既可以提供更强大的解决方案,也可以提供更具可扩展性的解决方案。