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);
                    }
                }
            }

     

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

  • 相关阅读:
    sql server 分页
    省市区
    省市
    sql server 中英混合排序
    C# 添加大量sql
    小程序小数的输入判定
    C# Files 的值“<<<<<<< .mine”无效。路径中具有非法字符。
    vagrant安装遇到的问题
    vagrant安装使用
    tp6 session问题
  • 原文地址:https://www.cnblogs.com/shanyou/p/386012.html
Copyright © 2011-2022 走看看