在 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);
}
我读了这个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);
}