2014-01-27 81 views
0

在WCF發佈/訂閱設置中,我當前有一個Unsubscribe()方法,用於在客戶端關閉或需要停止監聽時正常斷開客戶端與WCF主機的連接;但是,這並不處理客戶強行或異常中止的情況,例如電腦本身失去能力。如果客戶端應用程序以這樣的方式死去,那麼它的通道依然存在,在發佈它試圖發送郵件的下一次收到以下錯誤:WCF CommunicationException當訂閱客戶端中止異常

ExceptionDetail> was caught 
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it has been Aborted. 

客戶端訂閱匿名,併發布如下復播結構(任何訂閱的客戶/頻道都應該收到該消息)。儘管我能夠捕捉到這個異常,但我不知道如何從代碼的這一點挑出錯誤的通道來處理它,並允許其他客戶端繼續接收消息。我發佈的代碼看起來類似如下:

public static void Publish(DateTime sendTimeStamp, DataTable sendTable) 
     { 
      InstanceContext context = new InstanceContext(null, new PublishStatus()); 
      MessagesClient publishingClient = new MessagesClient(context); 
      try { 
       publishingClient.PublishMessage(sendTimeStamp, sendTable); 

       if (publishingClient.State != CommunicationState.Faulted) 
        publishingClient.Close(); 
       else 
        publishingClient.Abort(); 
      } 
      catch (CommunicationException ex) 
      { 
       // This is where the error is caught 
      } 
      catch (TimeoutException ex) 
      { 

       publishingClient.Abort(); 
      } 
      catch (Exception ex) 
      { 
       publishingClient.Abort(); 
       throw ex; 
      } 
     } 

是可以分離從這點(在該異常首先在這個問題上拿起)出現故障的通道,並對其進行處理,以便發佈服務本身可以繼續發送消息?

+0

我真的不能得到它,因爲我看你是在談論服務器,但您提供的代碼非常看起來像客戶端的代碼。或者我誤解了一些東西? – Tony

+0

代碼來自發布者(Windows服務),它定期將消息發送給客戶端,他們訂閱並監聽消息。你是對的,因爲很多這個異常代碼通常也會在客戶端,儘管它是否會傳回消息。管理找到解決方案,但感謝您的時間。 =) – user2912928

回答

0

經過一些試驗和錯誤以及異常研究後,我的WCF主機中的另一個try-catch塊能夠取消訂閱錯誤地中止的客戶端,並使錯誤不再回到發佈服務。對同一類型的問題張貼在這裏一個簡單的版本,以防止別人絆倒:

public static event MessageEventHandler MessageEvent; 
     public delegate void MessageEventHandler(object sender, ServiceEventArgs e); 

     IClientContract callback = null; 
     MessageEventHandler messageHandler = null; 

     public void Subscribe() 
     { 
      callback = OperationContext.Current.GetCallbackChannel<IClientContract>(); 
      messageHandler = new MessageEventHandler(Publish_NewMessageEvent); 
      MessageEvent += messageHandler; 
     } 

     public void Unsubscribe() 
     { 
      MessageEvent -= messageHandler; 
     } 

     public void PublishMessage(DateTime timeStamp, DataTable table) 
     { 
      ServiceEventArgs se = new ServiceEventArgs(); 
      se.timeStamp = timeStamp; 
      se.table = table; 
      MessageEvent(this, se); 
     } 

     public void Publish_NewMessageEvent(object sender, ServiceEventArgs e) 
     { 
      try 
      { 
       // This callback was causing the error, as the client would no longer exist but the channel would still be open and trying to receive the message 
       callback.ReceiveMessage(e.timeStamp, e.table); 
      } 
      catch 
      { 
       // Unsubscribe the dead client. 
       Unsubscribe(); 
      } 
     }