ASP.NET使用Dictionary出错
我先描述一下场景:系统面向多个企业用户,登陆时需要保存登录信息,割------------------------------------------------------------------------------------------------------------------贴代码:
private static string app_user = "app_user";
/// <summary>
/// 用户登录处理Application["LoginUserList"]
/// </summary>
/// <param name="loginUser"></param>
public void Login(LoginUser loginUser)
{
try
{
lock (app_user)
{
Dictionary<string, List<string>> LoginUserList = Application["LoginUserList"] as Dictionary<string, List<string>>;
if (LoginUserList == null)
{
LoginUserList = new Dictionary<string, List<string>>();
}
//判断LoginUserList是否存在企业enterpriseID
//如果包含,则找到企业key
if (LoginUserList.ContainsKey(loginUser.Enterprise_Code))
{
List<string> list = LoginUserList[loginUser.Enterprise_Code];
//如果该企业不包含user,则添加
if (!list.Contains(loginUser.UserID))
{
LoginUserList[loginUser.Enterprise_Code].Add(loginUser.UserID);
}
}
//如果不包含,则添加
else
{
LoginUserList.Add(loginUser.Enterprise_Code, new List<string> { loginUser.UserID });
}
Application["LoginUserList"] = LoginUserList;
}
}
catch (Exception ex)
{
string errorTitle = "保存用户登录信息出错";
string errorMsg = " 登陆人:" + loginUser.UserID + ", 登录时间:" + DateTime.Now + ", 错误信息:" + ex.Message;
Utility.Log.log.Error(errorTitle + errorMsg);
Model.Sys_Email model = new Model.Sys_Email(errorTitle, errorMsg);
new DAL.Sys_Email().Add(model);
}
}
简单讲解一下:Dictionary<string, List<string>> 第一个参数是企业ID,第二个参数是企业下的在线用户集合
再贴出下线代码:
/// <summary>
/// 用户注销处理Application["LoginUserList"]
/// </summary>
/// <param name="userID">用户ID</param>
/// <param name="enterpriseID">用户所属企业ID</param>
public void Logoff(string userID, string enterpriseID)
{
try
{
lock (app_user)
{
Dictionary<string, List<string>> LoginUserList = Application["LoginUserList"] as Dictionary<string, List<string>>;
if (LoginUserList == null)
{
return;
}
if (LoginUserList.ContainsKey(enterpriseID))
{
LoginUserList[enterpriseID].Remove(userID);
if (LoginUserList[enterpriseID].Count == 0)
{
LoginUserList.Remove(enterpriseID);
}
//注销掉Application[userid]
Application.Remove(userID);
Application.Remove(userID + "_ip");
}
Application["LoginUserList"] = LoginUserList;
}
}
catch (Exception ex)
{
string errorTitle = "用户注销时出错";
string errorMsg = " 登陆人:" + userID + ", 登录时间:" + DateTime.Now + ", 错误信息:" + ex.Message;
Utility.Log.log.Error(errorTitle + errorMsg);
Model.Sys_Email model = new Model.Sys_Email(errorTitle, errorMsg);
new DAL.Sys_Email().Add(model);
}
}
有的时候用户直接关闭浏览器,这时我会在session_end事件里执行下线操作
Ok,以上场景和代码介绍完毕,问题来了,有时候用户登录,会报错,错误日志如下:
There was an error in serializing one of the headers in message UserPassIsEditedRequest: 'Hashtable insert failed. Load factor too high. The most common cause is multiple threads writing to the Hashtable simultaneously.'. Please see InnerException for more details.
期大概意思是:哈希表插入失败了。负载率过高。最常见的原因是多个线程同时写入Hashtable。
为这个问题纠结了很久,也看了很多关于Hashtable和Dictionary的安全性问题,加了lock锁,还是会发生以上错误,请教各位大侠们解释。 --------------------编程问答-------------------- --------------------编程问答-------------------- 有人问为什么加字符串锁,这里我也搞不清楚深意。。。只是之前查了很多资料说这样有用,就加了,看来是没什么作用,有人出主意说加全局锁,试试看,不知道可否重现 --------------------编程问答-------------------- 这个,不是蛮清楚,帮忙顶一下 --------------------编程问答-------------------- Application应该是全局的,所有client访问的时候都是在共享同一个,app_user也是全局静态的,看起来不应该有问题,写点日志吧,看下在那行代码出的问题~~~ --------------------编程问答--------------------
private static Int32 _timeout = 50 * 1000;楼主 加上锁试下 --------------------编程问答-------------------- 为什么不用ConcurrentDictionary<T1, T2>呢
private static ReaderWriterLock rwl = new ReaderWriterLock();
public static Dictionary<int, ChatInfo> dictChats = new Dictionary<int, ChatInfo>();
public static List<ChatInfo> Chats = new List<ChatInfo>();
public static void Add(ChatInfo chat)
{
rwl.AcquireWriterLock(_timeout);
Chats.Add(chat);
dictChats.Add(chat.ChatID, chat);
rwl.ReleaseWriterLock();
}
补充:.NET技术 , C#