前一段时间写了一个定期查询在线用户有无消息提醒的功能大概实现是这样:在服务器端写了一个服务,首先开启UDP监听、2个Timer1.定时查询在线用户提醒消息数据库状态-5秒Timer,查询到的结果添加至一个待办的HashTable中
2.定时查询待办的HashTable,发送消息-5秒Timer客户端接收到消息后返回收到信息,删除HashTable对应值还有一个验证服务器是否在线的方法,就是客户端定时给服务器发验证,服务器回发这样。公司人很多(大概500),上班直接开启客户端,开始是没问题,一段时间之后经测试客户端还是能收到服务器在线的数据报,但是收不到提醒消息,数据库状态为提醒,貌似是服务不走查询消息那个Timer了...求高手解答,或者给一个此功能其他的解决方案。要求效率第一……

解决方案 »

  1.   

    服务问题啊,可能是服务死了
    最好调试一下服务。服务问题很麻烦的,有时候服务CPU 大, 或者内存一直猛涨 都会导致服务问题的。
    及时释放资源
      

  2.   

    首先感谢各位的热心帮助如何释放资源?服务应该是没死,我测试的客户端还是可以收到服务器的验证信息,就是查询数据那个Timer好像不执行了,服务器没有VS,另外这种UDP的服务也不好进行调试……
      

  3.   

    发现了一个问题,就是我用foreach (DictionaryEntry var in htTodo)遍历的HashTable,但是这个时候由于客户端返回接收成功信息,就把对应的htTodo记录删了,就会报"集合已修改;可能无法执行枚举操作"错误。这个错误会不会影响到服务的稳定性,还有如何遍历HashTable才可以在外部修改?
      

  4.   


    我想问的就是这个。。for怎么循环HashTable?
      

  5.   

    第一,查询数据库可以考虑用nolock来改善查询deadlock问题, 第二,为什么不用hashtable[key]来直接获取记录和hashtable.Remove[key]来删除记录,第三,多线程访问hashtable最好用readerwriterlockslim来保护,或者可以缓存用户的反馈消息,不要立即对hashtable进行删除,以防止同一个用户的一个待处理新的消息被删除
      

  6.   

    贴出代码,麻烦帮我修改一下"集合已修改,可能无法执行枚举操作"的问题这个是查询数据库Timer查到有提醒信息时候添加到HashTable的方法 private void SaveList(Hashtable _htRemind)
            {
                try
                {
                    foreach (DictionaryEntry var in _htRemind)
                    {
                        if (!htTodo.ContainsKey(var.Key))
                        {
                            htTodo.Add(var.Key, var.Value);
                        }
                    }
                }
                catch (Exception exp)
                {
                    FileLog.WriteErrLog(exp.ToString());
                }
            }
    这个是监听到客户端返回接收成功信息的方法private void UpdateRemind(string _remote, EndPoint _sender)
            {
                try
                {
                    if (htTodo.ContainsKey(Convert.ToInt32(_remote.Split('|')[1])))
                    {
                        htTodo.Remove(Convert.ToInt32(_remote.Split('|')[1]));
                        remind.UpdateRemind(_remote.Split('|')[1]);
                    }
                }
                catch (Exception exp)
                {
                    FileLog.WriteErrLog(exp.ToString());
                }
            }
    这个是现在报错的方法,提醒消息列表Timer发送的方法void listTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                string txt = "待办数目:" + htTodo.Count.ToString() + System.Environment.NewLine + DateTime.Now.ToString();
                FileLog.WriteListLog(txt);
                
                if (htTodo.Count != 0)
                {
                    try
                    {
                        foreach (DictionaryEntry var in htTodo)  ----如果接收到客户端成功消息,删除Hashtable对应值,则集合已修改,走Catch跳出循环,等待下一次Timer……
                        {
                            string _iRMOper = GetiRMOper(var.Value.ToString());
                            EndPoint userEP = GetUserAddress(_iRMOper);
                            if (userEP != null)
                            {
                                byte[] byteMsg = Encoding.Default.GetBytes(MSG + "|" + var.Key + "|" + var.Value + "|");
                                sock.SendTo(byteMsg, userEP);                            //Thread.Sleep(5000);
                            }
                        }
                    }
                    catch (Exception exp)
                    {
                        FileLog.WriteErrLog(exp.ToString());
                    }
                }        }
    如果解决这个错误问题呢,让它不跳出循环,怎么用for循环Hashtable