在 signalr 中跟踪在线用户:我应该在哪里创建 PresenceManager 实例以及如何将参数心跳传递给它

Tracking online users in signalr: where I should create instance of PresenceManager and how to pass the parameter heartbeat to it

我读了这个topic,它是关于增强使用数据库跟踪在线用户的方法。简而言之,该方法使用以下数据库:

public class ConnectedClient
{
    public long ID { get; set; }
    [StringLength(100)]
    public string ConnectionId { get; set; }
    public ConnectionStatus Status { get; set; }
    public string ApplicationUserID { get; set; }
    public string UserAgent { get; set; }
    public DateTimeOffset LastActivity { get; set; }

    //Relationship
    public ApplicationUser ApplicationUser { get; set; }
}

以及跟踪在线用户:

public class PresenceManager
    {
        private const int zombiePeriodThreshold = 2;
        private readonly ITransportHeartbeat _heartbeat;
        private readonly TimeSpan _checkInterval = TimeSpan.FromSeconds(60);
        private readonly int _zombieThreshold;
        private Timer timer;

        public PresenceManager(ITransportHeartbeat heartbeat)
        {
            _heartbeat = heartbeat;
            _zombieThreshold = (int)_checkInterval.TotalSeconds * zombiePeriodThreshold;
        }

        public void StartMonitoring()
        {
            if (timer == null)
            {
                timer = new Timer(t =>
                {
                    try
                    {
                        Check();
                    }
                    catch (Exception ex)
                    {
                        Trace.TraceError(ex.Message);
                    }
                }, null, TimeSpan.Zero, _checkInterval);
            }
        }

        //EF6 adds much better support for contains in queries http://bit.ly/1wmQ2VQ
        private void Check()
        {
            using (var db = new ApplicationContext())
            {
                //Update active connections
                var activeConnections = _heartbeat.GetConnections().Where(b => b.IsAlive).Select(b => b.ConnectionId);
                db.ConnectedClients
                    .Where(c => activeConnections.Contains(c.ConnectionId))
                    .ToList()
                    .ForEach(c => c.LastActivity = DateTimeOffset.UtcNow);

               //Remove zombie connections
               var zombies = db.ConnectedClients.Where(c => SqlFunctions.DateDiff("ss", c.LastActivity, DateTimeOffset.UtcNow) >= _zombieThreshold).ToList();
               var zombieUserIDs = zombies.Select(b => b.ApplicationUserID);
               db.Users
                   .Where(c => zombieUserIDs.Contains(c.Id))
                   .Where(c => c.ConnectedClients.Count <= 1)
                   .ToList()
                   .ForEach(u => u.Status = UserStatus.Offline);

                db.ConnectedClients.RemoveRange(zombies);
                db.SaveChanges();
            }
        }

    }

我理解上面的所有代码,我唯一不知道的是我应该在哪里创建 PresenceManager 的实例以及如何将参数 heartbeat 传递给它。

看看这里提供的答案。

虽然问题与您的问题没有直接关系,但他们无意中回答了在哪里创建 PresenceManager 实例以及如何将参数 heartbeat 传递给它:

public void ConfigureSignalR(IAppBuilder app) {
    var heartBeat = GlobalHost.DependencyResolver.Resolve<ITransportHeartbeat>(); 
    var monitor = new PresenceMonitor(heartBeat); 
    monitor.StartMonitoring();
    // Any connection or hub wire up and configuration should go here 
    app.MapSignalR();
}

然后像这样从主启动中调用它

public void Configuration(IAppBuilder app) {
    ConfigureAuth(app);
    ConfigureSignalR(app);
}