【问题标题】:CommunicationObjectAbortedException & CommunicationObjectFaultedException in WCF ServiceWCF 服务中的 CommunicationObjectAbortedException 和 CommunicationObjectFaultedException
【发布时间】:2013-01-04 18:54:57
【问题描述】:

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

服务:

[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 方法中。我从所有测试中得出的一个原因是,当客户端异常关闭时会发生这种情况。例如,客户端进程从任务管理器等中关闭。

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

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

谢谢。 乌默尔

【问题讨论】:

  • 很可能是超时或暂时的网络问题。我会运行WCF trace 看看它是否有关于发生的事情的更详细信息。

标签: wpf wcf exception service


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

    这样做的方法是,每次需要进行 WCF 调用时,打开通道,进行调用,然后关闭通道。

    这种方法提供了更强大和更可扩展的解决方案。

    【讨论】:

    • 感谢您的回复。我们需要客户端持续连接到服务。因为每当出现新信号时,服务器都会触发一个事件,然后将其发送到所有连接的客户端,即这是一个发布-订阅模式。有没有其他方法可以避免这些问题?
    • 在一个项目中,我们在每个 WPF 客户端上运行 WCF 服务器。当客户端启动时,它会向主服务器注册自己。然后主服务器可以对每个 WPF 应用程序进行 WCF 调用。
    猜你喜欢
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2010-11-17
    • 1970-01-01
    • 2011-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多