gpt4 book ai didi

c# - 在 SignalR Core disconnect 事件中等待几秒钟而不阻止应用程序存在

转载 作者:太空宇宙 更新时间:2023-11-03 22:31:00 25 4
gpt4 key购买 nike

在我的集线器的 OnDisconnectedAsync 事件中,我想等待几秒钟,然后再执行某些操作。我试图让它异步使用 non-blocking Task.Delay :

    public override async Task OnDisconnectedAsync(Exception exception) {
var session = (VBLightSession)Context.Items["Session"];
activeUsers.Remove(session.User.Id);

await Task.Delay(5000);
if(!activeUsers.Any(u => u.Key == session.User.Id)) {
await Clients.All.SendAsync("UserOffline", UserOnlineStateDto(session));
}

await base.OnDisconnectedAsync(exception);
}

虽然这按预期工作,但我注意到我无法立即关闭控制台应用程序。似乎它等待 5 秒延迟完成。我该如何解决这个问题,即退出应用程序也只是退出那些延迟?

我看到的唯一选择是 Creating a classic thread and inject IHubContext ,但这似乎不能很好地扩展,并且对于这个简单的任务来说有点矫枉过正。

背景

我有一个在线用户列表。当用户在多页面应用程序中导航时,他们会在新的 HTTP 请求期间短时间断开连接。为了避免在线列表中的这种闪烁(用户下线并再次直接在线),我想从用户列表中删除断开连接时的用户,但不立即通知 WS 客户端。

相反,我想等待 5 秒钟。只有当客户端仍然不在列表中时,我才知道客户端没有重新连接,我会通知其他用户。为此,我需要在断开连接事件时休眠。上述解决方案运行良好,除了应用程序退出延迟(这在开发过程中很烦人)。

出于某些原因,不应使用像 Angular 或其他框架这样的单页应用程序,主要是性能和 SEO。

最佳答案

我了解了 CancellationToken ,它可以传递给 Task.Wait。它可用于中止任务。使用 CancellationTokenSource 创建这样的 token 似乎可以很好地以编程方式取消 token (例如,在某些情况下)。

但我发现the ApplicationStopping token in the IApplicationLifetime interface ,在应用程序关闭时请求取消。所以我可以简单地注入(inject)

namespace MyApp.Hubs {
public class MyHub : Hub {
readonly IApplicationLifetime appLifetime;
static Dictionary<int, VBLightSession> activeUsers = new Dictionary<int, VBLightSession>();
public MyHub(IApplicationLifetime appLifetime) {
this.appLifetime = appLifetime;
}
}
}

只有在没有从该 token 请求取消时才休眠

public override async Task OnDisconnectedAsync(Exception exception) {
var session = (VBLightSession)Context.Items["Session"];
activeUsers.Remove(session.User.Id);
// Prevents our application waiting to the delay if it's closed (especially during development this avoids additionally waiting time, since the clients disconnects there)
if (!appLifetime.ApplicationStopping.IsCancellationRequested) {
// Avoids flickering when the user switches to another page, that would cause a directly re-connect after he has disconnected. If he's still away after 5s, he closed the tab
await Task.Delay(5000);
if (!activeUsers.Any(u => u.Key == session.User.Id)) {
await Clients.All.SendAsync("UserOffline", UserOnlineStateDto(session));
}
}
await base.OnDisconnectedAsync(exception);
}

这是有效的,因为在关闭应用程序时,SignalR 将此检测为断开连接(尽管它是由服务器引起的)。所以他在退出前等待了 5000 秒,就像我在我的问题中假设的那样。但是使用 token ,IsCancellationRequested 设置为 true,因此在这种情况下无需额外等待。

关于c# - 在 SignalR Core disconnect 事件中等待几秒钟而不阻止应用程序存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57828434/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com