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
}
最简单的方法是将您的导出客户端作为单例或静态变量,并在全局作用域中注册您的事件(可能在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));
}