如何使用signalR定期更新asp.net mvc视图?

时间:2019-02-08 14:11:19

标签: ajax asp.net-mvc signalr

现在,我使用来自视图的定期ajax调用来检索新数据。 我需要每2秒执行一次。控制器检查一些硬件/传感器信号。

是否可以使用signalR代替ajax?

我总是发现一些示例,其中一个视图上的更改会将新数据发送到所有其他视图(例如聊天程序)。 我还找到了signalR和sqldependencies,但是因此我需要将所有数据发送到sql服务器。

我还发现文章Realtime Maps Based On XML File Changes With SignalR正在使用“ FileSystemWatcher”检查xml文件更改。 是否可以“编织”另一个“ SystemWatcher”来检查我的传感器数据?

2 个答案:

答案 0 :(得分:0)

由ajax请求触发的控制器是否完成了硬件/传感器检查?

由于使用SignalR,因此您可能会产生其他一些数据,例如,在聊天应用程序中,用户将消息发布到控制器,控制器通过SignalR将消息发送给其他客户端。

在您的情况下,您需要执行一些硬件/传感器检查。这可能是:

  • 检查硬件/传感器的背景线程
  • 检查传感器并发布到asp.net MVC应用的计划任务

无论哪种方式,当后台线程检测到更改或您的控制器从计划任务中收到包含更新数据的帖子时,您都可以通过SignalR向您的客户发送消息。

这样,您就不会让客户一直在轮询。但是,您仍然需要定期检查传感器数据的内容,除非,您的传感器/硬件具有某种 push 方法可以向您发送数据。

如果您需要自己从传感器中提取数据,并且只有1个客户端,那么与仅进行ajax轮询相比,SignalR不会带来太多好处。但是,如果您有N个客户端,您将获得很大的好处,因为您只有1个线程读取数据并将数据推送到客户端,而不是N个读取数据。

一旦弄清楚了在控制器中获取数据的方式,SignalR将其发送给客户端的用法应与您所引用的消息传递示例相同,这些文档应向您展示如何实现它。 / p>

答案 1 :(得分:0)

现在我有以下解决方案。有人可以检查我的代码(如果这是常见的方法),或者我会遇到麻烦吗?

首先,我创建了一个中心类“ MyHub.cs” 我必须使用延迟初始化吗? 可以使用“重新连接”部分吗?

 [HubName("data")]
    public class DataHub : Hub
    {
        List<LineUser> userList = new List<LineUser>();
        public static ConcurrentDictionary<string, LineUser> MyUsers = new ConcurrentDictionary<string, LineUser>();

        public override Task OnConnected()
        {
            var context = GlobalHost.ConnectionManager.GetHubContext<DataHub>();

            string userConnectionID = Context.ConnectionId;
            MyUsers.TryAdd(Context.ConnectionId, new LineUser() { ConnectionID = Context.ConnectionId });

            return base.OnConnected();
        }

        public override Task OnReconnected()
        {
            var context = GlobalHost.ConnectionManager.GetHubContext<DataHub>();

            string userConnectionID = Context.ConnectionId;

            if (MyUsers.TryAdd(Context.ConnectionId, new LineUser() { ConnectionID = Context.ConnectionId }))
                _userCount++;

            var resconnectedUser = new LineUser();
            MyUsers.TryGetValue(userConnectionID, out resconnectedUser);
            Groups.Add(userConnectionID, resconnectedUser.LineNr.ToString());

            return base.OnReconnected();
        }

        public override Task OnDisconnected(bool stopCalled)
        {
            var context = GlobalHost.ConnectionManager.GetHubContext<DataHub>();

            string userConnectionID = Context.ConnectionId;

            LineUser garbage;

            var disconnectedUser = new LineUser();
            MyUsers.TryGetValue(userConnectionID, out disconnectedUser);
            Groups.Remove(userConnectionID, disconnectedUser.LineNr.ToString());

            MyUsers.TryRemove(userConnectionID, out garbage);

            return base.OnDisconnected(stopCalled);
        }

        [HubMethodName("registerName")]
        public void RegisterConId(int LineNr, string userConnectionID)
        {
            var oldUser = new LineUser();
            var newUser = new LineUser();
            newUser.LineNr = LineNr;
            newUser.ConnectionID = userConnectionID;
            newUser.Connected = true;

            MyUsers.TryGetValue(userConnectionID, out oldUser);

            MyUsers.TryUpdate(userConnectionID, newUser, oldUser);

            Groups.Add(userConnectionID, LineNr.ToString());
        }

    }

然后我用Quartz.net“ BackGroundJob.cs”创建了一个backgoundjob。 (应用程序启动后,将从类JobScheduler中每秒触发一次该事件)。 如果有新的传感器数据可用,我会将传感器数据发送到特定的组(该组名将在客户端调用HubMethodName“ registerName”之后创建。 因为传感器nr。 6个数据应仅发送给客户端nr。 6(所有nr。6的客户都在“ 6”组中)

  public class BackGroundJob : IJob
    {
        //Global variable to save the result between to background job executions
        SensorData oldsensorData = new SensorData();        

        public Task Execute(IJobExecutionContext context)
        {

            var newSensorData = ReadSensorData();

            if (!newSensorData.Equals(oldsensorData))
            {
                IHubContext hub = GlobalHost.ConnectionManager.GetHubContext<DataHub>();

                result = hub.Clients.Group(newSensorData.LineNr.ToString()).announceToLine("Sensor data for Line: " + newSensorData.LineNr.ToString() + " Temp: " + newSensorData.Temp.ToString());

                //Save new data to global object
                oldsensorData = newSensorData;
            }

            throw new NotImplementedException();            
        }

        private SensorData ReadSensorData()
        {
            SensorData newSensorData = new SensorData();
            //Code block to read sensor data from external device and save it to "newSensorData" object

            return newSensorData;
        }
    }

我的客户视图如下: 1. LineData.cshtml

@{
    ViewBag.Title = "Line Data";
}

<h1>Linie: @ViewBag.LineNr</h1>

<h2>Temperature</h2>
<div id="sensorData"></div>

@section scripts{
    <script>
        var LineNr = parseInt(@ViewBag.LineNr);
    </script>

    <script src="~/signalr/js"></script>
    <script src="~/Scripts/my/SignalR.js"></script>
}

和2.我的SignalR.js

(function () {

    var myHub = $.connection.data;

    // start hub connection
    $.connection.hub.start()
        .done(function () {
            //Register line number for group name
            myHub.server.registerName(LineNr, $.connection.hub.id);
        })
        .fail(function () {
            alert("SignalR Error for Line " + LineNr + " !");
        });


    // try reconnect after 5s
    $.connection.hub.disconnected(function () {
        setTimeout(function () {
            $.connection.hub.start();
        }, 5000); // Restart connection after 5 seconds.
    });

    // Clients functions
    myHub.client.announceToLine = function (data) {
        $("#sensorData").html(data);
    }

})()