0x01 在线用户类,我的用户唯一性由ID和类型识别(因为在不同的表里)
public class UserIdentity : IEqualityComparer<UserIdentity>
{
internal UserIdentity() { }
public UserIdentity(int userId, int userType)
{
this.UserID = userId;
this.UserType = userType;
}
public int UserID { get; private set; }
public int UserType { get; private set; }
public bool Equals(UserIdentity x, UserIdentity y)
{
return x.UserID == y.UserID && x.UserType == y.UserType;
}
public int GetHashCode(UserIdentity obj)
{
return obj.UserID * (obj.UserType + 10);
}
}
public class AliveUser
{
private AliveUser() { }
public AliveUser(string sessionID, int userID, int userType)
{
this.SessionID = sessionID;
this.StartAt = DateTime.Now;
this.User = new UserIdentity(userID, userType);
}
public void SetExpires(DateTime expires)
{
this.Expires = expires;
}
public string SessionID { get; private set; }
public DateTime StartAt { get; private set; }
public DateTime Expires { get; private set; }
public UserIdentity User { get; private set; }
}
0x02 会话管理,线程+字典
public class AliveSessionHelper
{
static AliveSessionHelper()
{
thread.IsBackground = true;
thread.Start();
}
public static int TimeoutInMinutes = 1;
private static object syncObject = new object();
public static Dictionary<string, AliveUser> OnlineUsers = new Dictionary<string, AliveUser>();
public static Dictionary<UserIdentity, List<AliveUser>> GetOnlineUsers()
{
lock (syncObject)
{
var list = OnlineUsers.Values.ToList();
var grouping = list.GroupBy(x => x.User,new UserIdentity());
var dict = new Dictionary<UserIdentity, List<AliveUser>>(grouping.Count());
foreach (var item in grouping)
{
dict.Add(item.Key, item.ToList());
}
return dict;
}
}
public static void AddAliveUser(string sessionID, int userID, int userType)
{
AddAliveUser(new AliveUser(sessionID, userID, userType));
}
public static void AddAliveUser(AliveUser user)
{
lock (syncObject)
{
var aliveUser = OnlineUsers.ContainsKey(user.SessionID) ? OnlineUsers[user.SessionID] : null;
if (aliveUser == null)
{
OnlineUsers.Add(user.SessionID, user);
}
var expires = DateTime.Now.AddMinutes(TimeoutInMinutes);
OnlineUsers[user.SessionID].SetExpires(expires);
}
}
private static Thread thread = new Thread(ThreadStartBody);
private static void ThreadStartBody()
{
while (true)
{
lock (syncObject)
{
var delList = new List<Guid>();
var list = OnlineUsers.Values.ToList();
foreach (var item in list)
{
if (item.Expires.Subtract(DateTime.Now).TotalSeconds < 5)
{
OnlineUsers.Remove(item.SessionID);
}
}
}
Thread.Sleep(29);
}
}
}
0x03 控制器实现
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
[Authorize]
public class ApiController : AsyncController
{
public async Task<ActionResult> KeepAlive()
{
if (!User.Identity.IsAuthenticated) {
return null;
}
AliveSessionHelper.AddAliveUser(Session.SessionID, AdminUserService.Instance.CurrentUserID, 0);
return await Task.Delay(TimeSpan.FromSeconds(30)).ContinueWith(task =>
{
return JavaScript("$.getScript(‘/admin/api/keepalive‘);");
});
}
}
注意
1、[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]是必须的,否则刷新(重复调用)会锁死,原理熟手自己领会,新手照做即可。
2、/admin/api/keepalive 调用Action的是自身。
0x04 前端代码,需要jQuery。原生js本人不会,请自行搞定。
$(function () {
//KeepAlive
$.getScript(‘/admin/api/keepalive‘);
}
是不是感觉代码很简单?拷贝请注明来源博客园,作者孤独飞鸿
QQ625761566
.Net软件交流群283590657
原文:http://www.cnblogs.com/mrtiny/p/5170286.html