这两天做网站有个好友系统,需要检测用户在线与离线状态。自己想了个解决办法,主要是通过全局变量(hsUserOnLine ),保存用户在线状态,再开启一个系统线程不停的检测这个在线列表(hsUserOnLine ),而客户端在用户登录之后开启一个由界面引发的线程,不断更新这个全局变量(hsUserOnLine )中对应自己的在线状态。一下为主要步骤:
1.在Global.asax中建立全局Hashtable hsUserOnLine ,并建立外部访问属性HsUserOnline。
//
创建同步全局hashtable存放用户在线状态
private static Hashtable hsUserOnLine = Hashtable.Synchronized( new Hashtable());
/**/ /// <summary>
/// 用户在线列表(Key:用户ID,在线状态:0,1;离线状态:null,-1)
/// </summary>
public Hashtable HsUserOnline
... {
get
...{
return hsUserOnLine;
}
set
...{
hsUserOnLine = value;
}
}
private static Hashtable hsUserOnLine = Hashtable.Synchronized( new Hashtable());
/**/ /// <summary>
/// 用户在线列表(Key:用户ID,在线状态:0,1;离线状态:null,-1)
/// </summary>
public Hashtable HsUserOnline
... {
get
...{
return hsUserOnLine;
}
set
...{
hsUserOnLine = value;
}
}
2.在系统启动时开启系统线程不停的监听hsUserOnLine,没过一段时间将hsUserOnLine中的键值对值为"1"的置"0",值为"0"的置"-1",值为"-1"的清除。
在Application_Start事件中添加启动线程
System.Threading.Thread thListenUsers
=
new
System.Threading.Thread(ListenUserOnlineStatus);
thListenUsers.Start();
thListenUsers.Start();
线程调用的函数ListenUserOnlineStatus
/**/
/// <summary>
/// 监听程序
/// </summary>
private void ListenUserOnlineStatus()
... {
try
...{
while (true)
...{
hstemp = new Hashtable();
lock (hsUserOnLine.SyncRoot)
...{
foreach (DictionaryEntry tempitem in hsUserOnLine)
...{
if (tempitem.Value.ToString() == "1")
...{
hstemp.Add(tempitem.Key, "0");
}
else if (tempitem.Value.ToString() == "0")
...{
hstemp.Add(tempitem.Key, "-1");
}
}
hsUserOnLine = Hashtable.Synchronized(hstemp);
}
System.Threading.Thread.Sleep(6000);
}
}
catch
...{
}
}
/// 监听程序
/// </summary>
private void ListenUserOnlineStatus()
... {
try
...{
while (true)
...{
hstemp = new Hashtable();
lock (hsUserOnLine.SyncRoot)
...{
foreach (DictionaryEntry tempitem in hsUserOnLine)
...{
if (tempitem.Value.ToString() == "1")
...{
hstemp.Add(tempitem.Key, "0");
}
else if (tempitem.Value.ToString() == "0")
...{
hstemp.Add(tempitem.Key, "-1");
}
}
hsUserOnLine = Hashtable.Synchronized(hstemp);
}
System.Threading.Thread.Sleep(6000);
}
}
catch
...{
}
}
3.用户登录时,对hsUserOnLine中加入改用户记录,将值设为"1",并启动线程定期刷新(将值重置为"1")
添加在线记录
lock
(ApplicationInstance.HsUserOnline.SyncRoot)
... {
ApplicationInstance.HsUserOnline.Remove(userId);
ApplicationInstance.HsUserOnline.Add(userId, "1");
}
... {
ApplicationInstance.HsUserOnline.Remove(userId);
ApplicationInstance.HsUserOnline.Add(userId, "1");
}
线程不断增加在线记录
lock
(ApplicationInstance.HsUserOnline.SyncRoot)
... {
string userstatus = Convert.ToString(ApplicationInstance.HsUserOnline[userId.ToString()]);
if (string.IsNullOrEmpty(userstatus))
...{
ApplicationInstance.HsUserOnline.Add(userId.ToString(), "1");
}
else if (userstatus != "1")
...{
ApplicationInstance.HsUserOnline.Remove(userId.ToString());
ApplicationInstance.HsUserOnline.Add(user.userId.ToString(), "1");
}
}
... {
string userstatus = Convert.ToString(ApplicationInstance.HsUserOnline[userId.ToString()]);
if (string.IsNullOrEmpty(userstatus))
...{
ApplicationInstance.HsUserOnline.Add(userId.ToString(), "1");
}
else if (userstatus != "1")
...{
ApplicationInstance.HsUserOnline.Remove(userId.ToString());
ApplicationInstance.HsUserOnline.Add(user.userId.ToString(), "1");
}
}
注:其中涉及到线程,我用锁机制,利用hashtable的SyncRoot属性对hashtable进行加锁。