/// <summary>
    /// 会议服务 服务为单线程也就是只有一个实例,并且消息调用实例在第一次初始化的时候指明
    /// </summary>
    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, InstanceContextMode = InstanceContextMode.Single)]
    public class MeetingService : AVA.Meeting.IService.IMeetingService
    {
        /// <summary>
        /// 在这里保存进入当前会议的用户列表和回调方法
        /// </summary>
        public static Dictionary<IMeetingServiceCallback, ClientCallback>
            ListCallbackToUser = new Dictionary<IMeetingServiceCallback, ClientCallback>();如的WCF每一个连接上来的用户我都保存到ListCallbackToUser里面
然后我要给他们发送信息比如用        void UpdateUserList()
        {
            foreach (IMeetingServiceCallback callbackClient in ListCallbackToUser.Keys)
            {
                try
                {
                    callbackClient.UpdateUserList(ListCallbackToUser.Values.Select(l => l.User).ToList());
                }
                catch (System.ServiceModel.CommunicationObjectAbortedException)
                {
                }
            }
        }但是这里的:try catch这里能不能改为判断是否已经断开?(因为客户端可能没有向WCF更新断开信息,而还在WCF这里有他的登录信息,但其实他已经是断开 的)谢谢

解决方案 »

  1.   

    实时会议聊天可以用双工,那样实现比点对点先测试连接要容易。这种情况下,要保证双工的可靠性,就需要在服务端做记录,比如你这里给ListCallbackToUser里面所有人发送消息,如果有个别人发送失败(try-catch捕获),你再将这类失败的消息存放到另一个变量中,等以后对方上线(建立双工连接)后再一次性都发送给他。而客户端什么时候尝试重新连接,这就需要设个定时,比如每隔1分钟测试下连接状态,访问一个服务端的空方法(不带参数,不带返回值),成功则表面当前连接正常,失败则是连接断开,尝试重新连接,并设定重试次数(如果断网了,怎么都不可能连上)。
      

  2.   

    因为你是双工通信,所以应该可以在服务端监听Channel.Closing事件。using System;
    using System.Collections.Generic;
    using System.ServiceModel;
    namespace WcfDuplexMessageService
    {
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]  
        public class MessageService : IMessageService, IDisposable 
        {
            public static List<IClient> ClientCallbackList { get; set; }
            public MessageService()
            {
                ClientCallbackList = new List<IClient>();
            }
            public void RegisterClient()
            {
                var client = OperationContext.Current.GetCallbackChannel<IClient>();
                var id = OperationContext.Current.SessionId;
                Console.WriteLine("{0} registered.", id);
                OperationContext.Current.Channel.Closing += new EventHandler(Channel_Closing);
                ClientCallbackList.Add(client);
            }
            void Channel_Closing(object sender, EventArgs e)
            {
                lock (ClientCallbackList)
                {
                    ClientCallbackList.Remove((IClient)sender);
                }
            }
            public void Dispose()
            {
                ClientCallbackList.Clear();
            }
        }
    }