Asp .net core SignalR 发送实时数据
Asp .net core SignalR send real time data
我有数据,我想将其呈现给用户而无需他刷新页面。
我正在使用 Asp .net 核心 SignalR,如下所示:
using System.Threading;
using Microsoft.AspNetCore.SignalR;
using WSEP212.DomainLayer;
namespace WebApplication.Publisher
{
public class ChartNotifications : Hub
{
// Create the instance of ChartDataUpdate
// Send Data every 1 seconds
readonly int _updateInterval = 1000;
//Timer Class
private Timer _timer;
private volatile bool _sendingChartData = false;
private readonly object _chartUpateLock = new object();
PieChart pieChart = new PieChart();
public ChartNotifications() {}
public void InitChartData()
{
//Show Chart initially when InitChartData called first time
pieChart.SetPieChartData();
sendChartData(pieChart);
//Call GetChartData to send Chart data every chosen interval
GetChartData();
}
public void GetChartData()
{
_timer = new Timer(ChartTimerCallBack, null, _updateInterval, _updateInterval);
}
private void ChartTimerCallBack(object state)
{
if (_sendingChartData)
{
return;
}
lock (_chartUpateLock)
{
if (!_sendingChartData)
{
_sendingChartData = true;
pieChart.SetPieChartData();
sendChartData(pieChart);
_sendingChartData = false;
}
}
}
public async void sendChartData(PieChart chart)
{
await Clients.All.SendAsync("updateChart", chart.GetPieChartData());
}
}
}
但我得到一个错误 -> System.ObjectDisposedException:无法访问已处置的对象。
对象名称:'ChartNotifications'.
在客户端看起来像这样:
chartConnection.start().then(() => {
console.log("chart connection started");
chartConnection.invoke('InitChartData');
});
你能告诉我我做错了什么吗?或任何其他使用 signalR 来完成此任务的想法?
我是新手,如果您能详细说明您的答案,请多多指教。
提前致谢!!
这不是推荐的方法。 documentation 明确表示 'Hubs are transient' 和“不要将状态存储在集线器 class 上的 属性 中。每个集线器方法调用都在新的集线器实例上执行。所以你想做的事情,无法通过这种方式实现。
我建议您改为执行的操作(未提供代码,只是对体系结构的一些想法):
- 添加一个Hosted Service
- 您可以将
IServiceProvider
传递给服务构造函数
- 让服务控制一个计时器;当计时器结束时,您可以使用服务提供者创建一个
IServiceScope
并请求一个 IHubContext<ChartNotifications>
的实例(参见 documentation)
- 使用该上下文将更新的数据发送到连接的客户端
我有数据,我想将其呈现给用户而无需他刷新页面。 我正在使用 Asp .net 核心 SignalR,如下所示:
using System.Threading;
using Microsoft.AspNetCore.SignalR;
using WSEP212.DomainLayer;
namespace WebApplication.Publisher
{
public class ChartNotifications : Hub
{
// Create the instance of ChartDataUpdate
// Send Data every 1 seconds
readonly int _updateInterval = 1000;
//Timer Class
private Timer _timer;
private volatile bool _sendingChartData = false;
private readonly object _chartUpateLock = new object();
PieChart pieChart = new PieChart();
public ChartNotifications() {}
public void InitChartData()
{
//Show Chart initially when InitChartData called first time
pieChart.SetPieChartData();
sendChartData(pieChart);
//Call GetChartData to send Chart data every chosen interval
GetChartData();
}
public void GetChartData()
{
_timer = new Timer(ChartTimerCallBack, null, _updateInterval, _updateInterval);
}
private void ChartTimerCallBack(object state)
{
if (_sendingChartData)
{
return;
}
lock (_chartUpateLock)
{
if (!_sendingChartData)
{
_sendingChartData = true;
pieChart.SetPieChartData();
sendChartData(pieChart);
_sendingChartData = false;
}
}
}
public async void sendChartData(PieChart chart)
{
await Clients.All.SendAsync("updateChart", chart.GetPieChartData());
}
}
}
但我得到一个错误 -> System.ObjectDisposedException:无法访问已处置的对象。 对象名称:'ChartNotifications'.
在客户端看起来像这样:
chartConnection.start().then(() => {
console.log("chart connection started");
chartConnection.invoke('InitChartData');
});
你能告诉我我做错了什么吗?或任何其他使用 signalR 来完成此任务的想法? 我是新手,如果您能详细说明您的答案,请多多指教。
提前致谢!!
这不是推荐的方法。 documentation 明确表示 'Hubs are transient' 和“不要将状态存储在集线器 class 上的 属性 中。每个集线器方法调用都在新的集线器实例上执行。所以你想做的事情,无法通过这种方式实现。
我建议您改为执行的操作(未提供代码,只是对体系结构的一些想法):
- 添加一个Hosted Service
- 您可以将
IServiceProvider
传递给服务构造函数 - 让服务控制一个计时器;当计时器结束时,您可以使用服务提供者创建一个
IServiceScope
并请求一个IHubContext<ChartNotifications>
的实例(参见 documentation) - 使用该上下文将更新的数据发送到连接的客户端