Asp.NET MVCのときめき/ロングコネクション

8396 ワード

0 x 01オンラインユーザークラス、私のユーザー一意性は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; }
    }

 
0 x 02セッション管理、スレッド+辞書
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);
            }
        }
    }

 
0 x 03コントローラ実装
 
[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.SessionState.SessionStateBehavior.ReadOnly)]は必須です.そうしないと、リフレッシュ(繰り返し呼び出し)がロックされ、原理が熟練しているので自分で理解し、初心者がそのようにすればいいです.
2,/admin/api/keepalive呼び出しのActionは自身である.
3、サービス側は要求の解放間隔を制御する.ここに設置されている30 s.1分を超えるとActionタイムアウトが発生する可能性がある場合は、AsyncTimeoutAttributeプロパティを追加して、解放間隔よりもActionタイムアウト時間を設定する必要があります.
 
0 x 04フロントエンドコード、jQueryが必要です.最初の呼び出しがトリガーされ、サービス側でjsに戻って自動的に実行されます.
$(function () {
         //KeepAlive
         $.getScript('/admin/api/keepalive');
}

 
コードが簡単だと思いますか?シンプルで実用的で使いやすいことを重視するのはブロガーの一貫した追求である.
 
コピーはソースブログ園、道木さんを明記してください.のNetソフトウェア交流群283590657