Отчет о ходе работы с использованием интерфейса SignalR и IProgress

#javascript #c# #signalr

#c# #asp.net-mvc #websocket #signalr #signalr-концентратор

Вопрос:

У меня есть класс Hub, который имеет длительный метод, мне нужно отображать индикатор выполнения, пока он работает.

Я прочитал эту статью и думаю, что можно использовать интерфейс IProgress в асинхронных методах для отправки статуса длительной работы.

Я пишу метод, подобный этому:

     public async Task<string> GetServerTime(IProgress<int> prog)
    {
        await Task.Run(() => {
            for (int i = 0; i < 10; i  )
            {
                prog.Report(i * 10);
                System.Threading.Thread.Sleep(200);
            }
        });

        return DateTime.Now.ToString();
    }
  

И я пытаюсь вызвать метод следующим образом:

  var appHub = $.connection.appHub;
 $.connection.hub.start();
 appHub.server.getServerTime()
              .done(function (time) {
                    alert(time);
               });
  

Но я не знаю, как я могу получить отчеты о ходе выполнения.

Комментарии:

1. Привет, вы должны создать экземпляр IProgress на клиенте и передать его функции getServerTime. Затем вы регистрируетесь на событие в IProgress на клиенте, чтобы делать свои вещи

2. Спасибо, как я могу создать экземпляр на клиенте ?!

Ответ №1:

Вы можете использовать progress , как таковой:

 var appHub = $.connection.appHub;
$.connection.hub.start().done(function() {
  appHub.server.getServerTime()
    .progress(function (update) { alert(update); })
    .done(function (time) { alert(time); });
});
  

Кстати, нет смысла использовать Task.Run код, привязанный к процессору, на стороне сервера. Ваш серверный код с таким же успехом может быть:

 public string GetServerTime(IProgress<int> prog)
{
    for (int i = 0; i < 10; i  )
    {
        prog.Report(i * 10);
        System.Threading.Thread.Sleep(200);
    }

    return DateTime.Now.ToString();
}
  

Ваши методы на стороне сервера должны выполняться только async в том случае, если они выполняют настоящую асинхронную работу (обычно операции, связанные с вводом-выводом). Как правило, избегайте Task.Run на стороне сервера.

Комментарии:

1. Сначала я получил сообщение об ошибке, в котором говорится, что метод progress является неопределенным типом, затем я заменил jquery 1.6.4 , который я использовал, на jquery 1.11.1 , так что теперь он работает! спасибо @Stephen Cleary 🙂

2. Та же идея, что и @Stephen Cleary, рекомендованная в примере Дэмианом Эдвардсом / SignalR-2.x-demo github.com/DamianEdwards/SignalR-2.x-demo/blob/master/SignalR2x /…

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

Ответ №2:

В вашем javascript добавьте следующий клиентский метод

  var appHub = $.connection.appHub;
  $.connection.hub.start();
  appHub.client.progress = function(progresspct) {
     // logic for whatever you want to do.
  };

  appHub.server.getServerTime()
          .done(function (time) {
                alert(time);
           });
  

Измените код на стороне сервера следующим образом —

     public async Task<string> GetServerTime(IProgress<int> prog)
   {
    await Task.Run(() => {
        for (int i = 0; i < 10; i  )
        {
            prog.Report(i * 10);
            // Call to your client side method.
            Clients.Client(Context.ConnectionId).progress(i);
            System.Threading.Thread.Sleep(200);
        }
    });

    return DateTime.Now.ToString();
}