首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线程安全的Generic Dictionary

线程安全的Generic Dictionary

作者头像
张善友
发布2018-01-19 14:57:00
5750
发布2018-01-19 14:57:00
举报
文章被收录于专栏:张善友的专栏张善友的专栏

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);
                }
            }
        }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2006-04-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档