2013-01-21 21 views
7

Pracuję w systemie na podstawie wzoru wydawca abonenta. Mam usługę WCF, która działa w aplikacji WPF. Istnieje wielu klientów, którzy łączą się z usługą. Strona klienta to także WPF. Załączam fragmenty kodu z mojego systemu poniżej:CommunicationObjectAbortedException & CommunicationObjectFaultedException w WCF Służby

Usługa:

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

A mój 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> 

System działa doskonale na długie okresy bez żadnych problemów . Co się dzieje, że z jakiegoś powodu (o którym nie jestem entirley pewien) usługa czasami uderzył z wyjątkiem:

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

Sprawiedliwego powtórzyć, wyjątek ten występuje w metodzie PublishNewSignal. Jednym z powodów, który wyciągnąłem ze wszystkich testów, jest to, że dzieje się tak, gdy klient jest nienormalnie zamknięty. Na przykład, proces klienta jest zamknięta od menedżera zadań itp

Ale ten problem jest duży ból i nie możemy ruszyć forawrd bez mocowania tej stabilności problem. Czy ktokolwiek ma pojęcie, dlaczego obiekt komunikacyjny zostaje uszkodzony, a usługa ulega awarii?

nadzieję uzyskać jakąś pozytywną opinię w tej sprawie.

Dzięki. Umer

+0

Najprawdopodobniej problem z przekroczeniem limitu czasu lub przejściowym. Uruchomiłbym [ślad WCF] (http://msdn.microsoft.com/en-us/library/ms733025.aspx), aby sprawdzić, czy ma on bardziej szczegółowe informacje o tym, co się stanie. –

Odpowiedz

7

Po kilku badań, mam rozwiązać tej kwestii siebie. Problem polegał na tym, że ilekroć mój klient rozłączał się nieoczekiwanie bez odpowiedniego anulowania subskrypcji, a usługa nie zajmowała się prawidłowo upuszczonym klientem. Tak więc obiekt wspólnotowy został zarzucony. Lee's odpowiedź na this question naprawdę pomogła mi myśleć w dobrym kierunku. Po kilku dalszych badaniach, znalazłem this discussion bardzo przydatne w rozwiązaniu problemu.

1

Na podstawie tego, co zostało pokazane to wygląda po otwarciu kanału WCF (tworzenie klienta) po uruchomieniu aplikacji, a następnie nie zamykaj go, aż aplikacja się zamyka.

Istnieje kilka problemów z tym podejściem. To, na co się natkniesz, oznacza, że ​​jakiekolwiek zakłócenia w sieci lub serwerze spowodują, że kanał będzie nieużyteczny.

Sposobem na to jest fakt, że za każdym razem trzeba zrobić WCF zadzwonić otworzyć kanał, nawiązać połączenie, a następnie zamknąć kanał.

Takie podejście zapewnia zarówno bardziej niezawodne, jak i bardziej skalowalne rozwiązanie.

+0

Dzięki za odpowiedź. Potrzebujemy, aby klient był stale połączony z usługą.Ponieważ zawsze, gdy pojawia się nowy sygnał, serwer wywołuje zdarzenie, które jest następnie wysyłane do wszystkich podłączonych klientów, tj. Jest to wzorzec pub-sub. Czy jest jakiś inny sposób na zrobienie tego i uniknięcie problemów? –

+0

W jednym projekcie uruchamiamy serwer WCF na każdym kliencie WPF. Po uruchomieniu klient rejestruje się na serwerze głównym. Następnie główny serwer może wywoływać wywołania WCF do każdej aplikacji WPF. –