如何使用ASP强制服务器不断发送事件数据.. NET MVC + SignalR

本文关键字:数据 事件 NET MVC SignalR ASP 何使用 制服 服务器 | 更新日期: 2023-09-27 18:15:40

ExportClient类有OnTickRecieved事件,这有助于我接收一些数据(来自市场的出价)。所有我想要的-是接收这些数据实时在我的图表在浏览器。当我按下ui侧的Go按钮时,它在控制器中调用Go()方法,然后什么也没有发生。这是合乎逻辑的,因为在服务器上发出请求后,控制器就被销毁了。

我的问题是:如何强制服务器不断向我发送事件数据?

控制器

代码:

public class ChartsController : Controller
{
    [HttpGet]
    public void Go()
    {
        var exportClient = new ExportClient();
        exportClient.TickRecieved += exportClient_TickRecieved;
    }
    private void exportClient_TickRecieved(object sender, TickRecievedEventArgs args)
    {
        ImpulserHub.SendBidPrice(args.Bid);
    }
}

代码:

[HubName("impulserHub")]
public class ImpulserHub : Hub
{
   public static void SendBidPrice(double bid)
   {
       var hubContext = GlobalHost.ConnectionManager.GetHubContext<ImpulserHub>();
       hubContext.Clients.All.sendBidPrice(bid);
   }
}

我已经测试了SignalR,这个代码工作得很好:

[HttpGet]
public void Go()
{
   ImpulserHub.SendBidPrice(3.3333333); // I have received this number on UI
}

如何使用ASP强制服务器不断发送事件数据.. NET MVC + SignalR

最简单的方法是将您的导出客户端作为单例或静态变量,并在全局作用域中注册您的事件(可能在global .asax.cs的Application_Start()方法中)。您的集线器代码也应该移出,因为集线器像控制器一样是暂时的。

应该是这样的:

private ExportClient _exportClient;
private IHubContext _impulserHub;
protected void Application_Start()
{
    _exportClient = new ExportClient();
    exportClient.TickRecieved += exportClient_TickRecieved;
    _impulserHub = GlobalHost.ConnectionManager.GetHubContext<ImpulserHub>();
}
private void exportClient_TickRecieved(object sender, TickRecievedEventArgs args)
{
    _impulserHub.Clients.All.sendBidPrice(args.Bid);
}

这段代码仍然存在一个问题。IIS将关闭没有积极接收请求的网站。这意味着即使事件被触发,代码也可能随时停止工作。管理应用程序关闭是困难的,因为必须在应用程序启动和停止之间保存/传输状态。除非你可以设置IIS永远不会破坏你的应用程序(大多数时候在共享或云托管上是不可能的),你应该尝试使用HangFire库,它是一个nuget包。它是专门为该用例设计的,并且经过一些重构,您的代码可能看起来像这样:

private ExportClient _exportClient;
private IHubContext _impulserHub;
protected void Application_Start()
{
    _exportClient = new ExportClient();
    exportClient.TickRecieved += exportClient_TickRecieved;
    _impulserHub = GlobalHost.ConnectionManager.GetHubContext<ImpulserHub>();
    BackgroundJob.Schedule(() => _impulserHub.Clients.All.sendBidPrice(_exportClient.GetBid()), TimeSpan.FromSeconds(5));
}