zoukankan      html  css  js  c++  java
  • 线程安全的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);
                    }
                }
            }

     

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

  • 相关阅读:
    PS_0005:画带颜色在线条框 按住Alt键复制
    零钱兑换(动态规划)
    倒排索引原理和实现
    集群搭建
    java内部类
    nohup &后台运行脚本
    scala构造函数
    spark数据源读取及读数据原理
    安装redis解决公司linux环境的坑
    61、对于employees表中,给出奇数行的first_name
  • 原文地址:https://www.cnblogs.com/shanyou/p/386012.html
Copyright © 2011-2022 走看看