如果用户与 signalR 断开连接超过 10 分钟,我基本上是在尝试做一些数据库工作。我在 Hub 的 OnDisconnectedAsync() 中放置了一个计时器。我遇到的问题是我需要访问数据库的 ObjectDisposedException。当我绕过计时器并尝试直接在 OnDisconnectedAsync() 中进行调用时,我遇到了同样的问题。我想当我进入 OnDisconnectedAsync() 时,一切都已经被破坏了。
几天来我一直在尝试我能找到的一切,但似乎没有任何效果。处理此类问题的正确方法是什么?
public class RangeHub : Hub
{
private readonly IHubContext<RangeHub> _hubContext;
private readonly UserManager<ApplicationUser> _userManager;
private readonly IDashboardService _service;
private readonly ApplicationDbContext _context;
private readonly ISubscriptionService _subscription;
private readonly HOptions _hOptions;
//private Timer disconnectTimer = new Timer();
private CustomTimer disconnectTimer;
private string UserId
{
get
{
//return User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier).Value;
return Context.UserIdentifier;
}
}
public RangeHub(IHubContext<RangeHub> hubContext, UserManager<ApplicationUser> userManager, IDashboardService service, ApplicationDbContext context,
ISubscriptionService subscription, IOptionsMonitor<HOptions> hOptions)
{
_hubContext = hubContext;
_context = context;
_userManager = userManager;
_service = service;
_subscription = subscription;
_hOptions = hOptions.CurrentValue;
disconnectTimer = new CustomTimer
{
Interval = 30000,
AutoReset = false
};
disconnectTimer.Elapsed += DisconnectTimedEvent;
//disconnectTimer.Elapsed += (sender, e) => DisconnectTimedEvent(sender, e, UserId);
//disconnectTimer.Interval = 30000;//120000;
//disconnectTimer.AutoReset = false;
}
public override Task OnConnectedAsync()
{
Log.Information("OnConnectedAsync: CONNECT TO CLIENT");
System.Diagnostics.Debug.WriteLine("OnConnectedAsync: CONNECT TO CLIENT");
//If timer was running, stop timer/reset
if(disconnectTimer.Enabled)
{
//reset timer
disconnectTimer.Stop();
}
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
//TODO: This is firing off when the dashboard is left, need to fix
Log.Information("OnDisconnectedAsync: DISCONNECTED FROM CLIENT");
System.Diagnostics.Debug.WriteLine("OnDisconnectedAsync: DISCONNECTED FROM CLIENT");
_service.StopActiveEnvironment(UserId);
//_hubContext.Clients.
//TODO: place logic here to stop environment and stop user's time
disconnectTimer.userId = UserId;
disconnectTimer.dashService = _service;
disconnectTimer.dBContext = _context;
//disconnectTimer.Start();
//*is this for a single user? will this effect all users at once?
return base.OnDisconnectedAsync(exception);
}
public void DisconnectTimedEvent(object sender, ElapsedEventArgs e)//, IDashboardService dashService)
{
//Shut down the range
Log.Information("DEBUG Timer");
Log.Information("UserId: " + ((CustomTimer)sender).userId);
Log.Information("Shutting down environment due to signalR disconnection timer.");
//Van - 9-28-2019: Not using await here. This should be the last thing done before the instance of this class is destroyed.
// Using await takes too long and the Hub object is already destroyed before its finished.
//_service.StopActiveEnvironment(((CustomTimer)sender).userId);
//Task.Run(async () => await _service.StopActiveEnvironment("051735c4-fa6d-4d90-9f76-b540aaa110bc"));
//Task.Run(async () => await _service.StopActiveEnvironment("051735c4-fa6d-4d90-9f76-b540aaa110bc")).WaitAndUnwrapException();
try
{
var func = ((CustomTimer)sender).dashService.StopActiveEnvironment(((CustomTimer)sender).userId);
func.WaitAndUnwrapException();
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
}
class CustomTimer : Timer
{
public string userId;
public IDashboardService dashService;
public ApplicationDbContext dBContext;
}