Как периодически обновлять asv.net mvc view используя signalR? - PullRequest
0 голосов
/ 08 февраля 2019

Прямо сейчас я использую периодические ajax-вызовы из представления для получения новых данных.Мне нужно это каждые 2 секунды.Контроллер проверяет некоторые аппаратные / сенсорные сигналы.

Есть ли способ использовать signalR вместо ajax?

Я всегда находил примеры, когда изменения в одном представлении будут отправлять новые данные всем другим представлениям (как программа чата).Я также обнаружил, что signalR и sqldependencies, но для этого мне нужно отправить все данные на сервер sql.

Я также обнаружил, что статья Карты реального времени, основанные на изменениях файлов XML с помощью SignalR Они используют«FileSystemWatcher» для проверки изменений XML-файла.Можно ли «запилить» другого «SystemWatcher» для проверки данных моего датчика?

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Теперь у меня есть следующее решение.Может кто-нибудь проверить мой код, если это распространенный способ, или у меня возникнут какие-то проблемы?

Сначала я создал концентраторный класс "MyHub.cs". Нужно ли использовать ленивую инициализацию?Правильно ли работает раздел OnReconnected?

 [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());
        }

    }

Затем я создал backgoundjob с Quartz.net "BackGroundJob.cs" (этот будет запускаться каждую секунду из класса JobScheduler после запуска приложения).Если доступны новые данные датчика, я отправляю данные датчика в определенную группу (имя группы будет создано после того, как клиент вызовет HubMethodName «registerName». Поскольку данные датчика № 6 следует отправлять только клиенту № 6 (все клиентыс номером 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. my 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);
    }

})()
0 голосов
/ 08 февраля 2019

Проверка оборудования / датчика выполняется контроллером по запросу ajax?

Поскольку с SignalR идея заключается в том, что у вас есть что-то еще, что генерирует данные, например, в приложении чата aПользователь отправляет сообщение контроллеру, который отправляет сообщение через SignalR другим клиентам.

В вашем случае вам нужно что-то сделать для проверки оборудования / датчика.Это может быть:

  • Фоновый поток, который проверяет оборудование / датчик
  • Запланированное задание, которое проверяет датчик и отправляет сообщения в ваше приложение asp.net MVC

В любом случае, когда ваш фоновый поток обнаруживает изменение или ваш контроллер получает сообщение с обновленными данными из запланированного задания, вы можете отправить сообщение своим клиентам через SignalR.

Таким образом, у вас нет своегоклиенты опрашивают все время.Однако вам все равно нужно периодически что-то проверять данные вашего датчика, , если ваш датчик / аппаратное обеспечение не использует какой-либо метод push для отправки вам данных.

Если вам нужно извлечь данные из вашего датчика самостоятельно, и у вас есть только 1 клиент, вы не получите большой выгоды от SignalR по сравнению с простым опросом ajax.Однако, если у вас N клиентов, вы можете получить большую выгоду, потому что у вас будет только 1 поток, считывающий данные и отправляющий клиентам, а не N читающий их.

После того, как вы выясните способ получения данных в вашем контроллере, использование SignalR для отправки его вашим клиентам должно быть таким же, как в примере обмена сообщениями, на который вы ссылаетесь, эти документы должны показать вам, как реализоватьэто.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...