wpf WCF 服务中的 CommunicationObjectAbortedException 和 CommunicationObjectFaultedException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14443390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 07:08:53  来源:igfitidea点击:

CommunicationObjectAbortedException & CommunicationObjectFaultedException in WCF Service

wpfwcfexceptionservice

提问by Master.Aurora

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:

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

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:

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

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

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.

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

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

谢谢。乌默尔

采纳答案by Master.Aurora

After some research, i have solved this issue myself. The problem was that whenever my client disconnected unexpectedly without properly unsubscribing, and the service was not properly taking care of the dropped client. So the communciation object became faulted. Lee'sanswer to this questionreally helped me think in the right direction. Upon some more research then, i found this discussionpretty useful in solving the problem.

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

回答by Shiraz Bhaiji

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.

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

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.

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

This approach gives both a more robust as well as a more scalable solution.

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