2016-05-14 22 views
1

我使用WCF雙工在WCF服務器中訂閱的用戶之間發送/接收消息。 WCF有三種方法:Join(訂閱),Leave(取消訂閱)和SendAlert(將用戶的消息發送給其他用戶)。以下是服務器端代碼(服務器WCF雙工中的AlertService):客戶端在WCF雙工中突然崩潰時應該怎麼做

using System; 
using System.Collections.Generic; 
using System.ServiceModel; 

namespace RahatWCF 
{ 
    [ServiceContract(Name = "AlertService", 
        Namespace = "RahatWCF", 
        SessionMode = SessionMode.Required, 
        CallbackContract = typeof(IAlertCallback))] 
    public interface IAlert 
    { 
     [OperationContract] 
     int JoinTheConversation(int userId); 

     [OperationContract(IsOneWay = true)] 
     void SendAlert(int senderUserId, List<int> recieversUserId, string caption, string messageText); 

     [OperationContract] 
     int LeaveTheConversation(int userId); 
    } 

    public interface IAlertCallback 
    { 
     [OperationContract(IsOneWay = true)] 
     void NotifyUserOfMessage(int senderUserId, List<int> recieversUserId, string caption, String messageText); 
    } 

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.PerCall)] 
    public class AlertService : IAlert 
    { 
     private static List<IAlertCallback> _callbackList = new List<IAlertCallback>(); 

     public AlertService() { } 

     public int JoinTheConversation(int userId) 
     { 
      IAlertCallback registeredUser = OperationContext.Current.GetCallbackChannel<IAlertCallback>(); 

      if (!_callbackList.Contains(registeredUser)) 
       _callbackList.Add(registeredUser); 

      return _callbackList.Count; 
     } 

     public int LeaveTheConversation(int userId) 
     { 
      IAlertCallback registeredUser = OperationContext.Current.GetCallbackChannel<IAlertCallback>(); 

      if (_callbackList.Contains(registeredUser)) 
       _callbackList.Remove(registeredUser); 

      return _callbackList.Count; 
     } 

     public void SendAlert(int senderUserId, List<int> recieversUserId, string caption, string messageText) 
     { 
      _callbackList.ForEach(
       delegate (IAlertCallback callback) 
       { 
        callback.NotifyUserOfMessage(senderUserId, recieversUserId, caption, messageText); 
       }); 
     } 
    } 
} 

上面的代碼是我在服務器端實現的WCF雙工。當用戶登錄到應用程序時,我的WCF客戶端應用程序加入此WCF;當用戶從應用程序中註銷時,客戶端應用程序將離開WCF。問題是,如果用戶突然終止應用程序,而不是從客戶端應用程序註銷,則他/她以後不能向其他用戶發送消息。我檢查了這個問題,發現當用戶登錄(連接)並且不註銷(離開)時,在服務器中爲用戶創建兩個通道,並且在這種情況下SendAlert不再工作。我怎麼解決這個問題?

回答

0

超時是雙工通道的關鍵設置(如果沒有消息發送或接收)。將它們縮短並且您的頻道將會出錯。如果您從服務器發送響應,您可以對出現故障的客戶端通道做出反應,並將其從已知通道中刪除。如果客戶端出現故障,則需要重新加入服務器;在這種情況下,您可以從您的服務中刪除其他回調。

+0

我增加了'receiveTimeout'和'inactivityTimeout',但有時(我不知道爲什麼)我得到錯誤說'通信對象System.ServiceModel.Channels.ServiceChannel不能用於通信,因爲它具有已被中止。「我怎樣才能解決這個錯誤? – Mohsen

+0

你可以看看[重新連接邏輯](http://stackoverflow.com/questions/14547034/wcf-channelfactory-and-channels-caching-reusing-closing-and-recovery/22124269#22124269),但唯一可以做的就是重新創建頻道。 –

+0

謝謝。我會檢查並通知你。 – Mohsen