• 线程安全的Generic Dictionary



     
    System.Collections.Generic.Dictionary<,>

    只要不修改该集合,Dictionary 就可以同时支持多个阅读器。即便如此,从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。当出现枚举与写访问互相争用这种极少发生的情况时,必须在整个枚举过程中锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。今天解决了使用Dictionary泛型类的时候出现一个错误 “System.InvalidOpervationException "集合已经修改,可能无法执行枚举操作"”。原来的代码如下:

            private void CheckingTimeout() 
            {
                List
    <string> list = new List<string>();
                
    lock (sessions)
                {
                    
    foreach (string sessionKey in sessions.Keys)
                    {
                        
    if (sessions[sessionKey].IsTimeouted) 
                        {
                            logger.Info(
    "会话 [" + sessionKey + "] 超时");
                            UnLoadSession(sessionKey);
                            list.Add(sessionKey);
                        }
                    }
                    
    foreach (string key in list)
                    {
                        sessions.Remove(key);              
                    }
                }
            } 

          
    public void UnloadSession(string sessionID)
            {
                
    lock (sessions)
                {
                    
    if (sessions.ContainsKey(sessionID))
                    {
                        db.Delete(GetSessionFromDatabase(sessionID));
                        dispatcher.UnregisterAllOutEventSubscriber(sessionID);
                        sessions.Remove(sessionID);
                    }
                }
            }


    错误出现的原因是代码中在枚举的过程中修改了集合,而造成了这个错误,修改后的代码如下:
     

           private void CheckingTimeout()
            {
                List
    <string> list = new List<string>();
                
    lock (sessions)
                {
                    
    foreach (string sessionKey in sessions.Keys)
                    {
                        
    if (sessions[sessionKey].IsTimeouted)
                        {
                            logger.Info(
    "会话 [" + sessionKey + "] 超时");
                            UnregisterSession(sessionKey);
                            list.Add(sessionKey);
                        }
                    }
                    
    foreach (string key in list)
                    {
                        sessions.Remove(key);              
                    }
                }
            }

            
    private void UnregisterSession(string sessionID)
            {
                
    lock (sessions)
                {
                    
    if (sessions.ContainsKey(sessionID))
                    {
                        db.Delete(GetSessionFromDatabase(sessionID));
                        dispatcher.UnregisterAllOutEventSubscriber(sessionID);
                    }
                }
            }

     

    欢迎大家扫描下面二维码成为我的客户,为你服务和上云

  • 相关阅读:
    随堂练习 shell脚本(五)
    随堂练习 shell脚本(四)
    随堂练习 shell脚本(三)
    马哥博客作业第五周
    JavaScript连载25-正则表达式的匹配分割替换以及贪婪模式
    Java连载130-JDBC编程初步
    C连载15-练习一波转换模式
    Android连载25-强制下线具体实现
    JavaScript连载24-正则表达式
    Java连载129-广播数据包、网络编程总结
  • 原文地址:https://www.cnblogs.com/shanyou/p/386012.html
Copyright © 2020-2023  润新知