Добавьте обновление прогресса в реальном времени на медленную страницу в asp.net

Я пытаюсь добавить отчет о ходе выполнения в реальном времени в свое приложение С#/asp.net 4.0 для страницы с медленной загрузкой. Я просмотрел элементы управления UpdatePanel и UpdateProgress Ajax, но не думаю, что они подходят.

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

Порядок действий будет следующим: 1. пользователь нажимает кнопку для запуска 2. вызывает метод 1 3. когда метод 1 завершается, пользователь видит «Метод 1 выполнен» 3. вызывает метод 2 и т. д.

Может кто-нибудь помочь с этим?


person ShaneH    schedule 03.05.2011    source источник


Ответы (1)


Такое асинхронное выполнение может быть сложно реализовать. Несколько решений, которые пришли мне в голову:

Полностью асинхронный без AJAX:

  1. Используйте кнопку хитов, отправляет страницу.
  2. Сервер генерирует GUID для задачи и создает запись в вашей базе данных. Это может включать:

    • Guid (ID)
    • Флаг состояния/перечисление
    • начальное время.
  3. Сервер порождает поток для обработки задачи и передает Guid.

  4. Сервер возвращает GUID вместе с сообщением «Работает...».
  5. Через n секунд/миллисекунд/insert-time-span-here браузер снова отправляет страницу, включая команду «GetStatus» и GUID.
  6. Сервер проверяет флаг состояния в базе данных на основе GUID.
  7. Сервер возвращает сообщение о состоянии на основе записи БД ("Шаг 2...", "Все еще работает" или что-то другое)
  8. Повторяйте шаг (5), пока состояние, возвращаемое сервером, не будет указывать на завершение процесса.

В потоке, созданном на шаге (3):

  1. Начало потока
  2. Прочитать текущий статус из записи БД
  3. Выполните следующий шаг на основе этого статуса
  4. Обновите статус БД, чтобы указать, что она готова к следующему шагу, или установите флаг ошибки.
  5. Сон на несколько миллисекунд, чтобы не заблокировать приложение (может быть ненужным - я не уверен, как потоки взаимодействуют в IIS)
  6. Цикл к (2), пока все не будет сделано.
  7. Поток выходит.

Вот пример простого создания потока с помощью лямбды.

(new Thread(
    () => {
        DoLongRunningWork();
    }
) { Name = "Long Running Work Thread"
    ,
    Priority = ThreadPriority.BelowNormal 
    }).Start();

Синхронно

Проще, но может вызвать некоторые проблемы с производительностью:

  1. Пользователь отправляет форму «Старт».
  2. Сервер записывает «Начало...» в поток ответов и сбрасывает поток. Я думаю, это должно вернуть текст клиенту, но я не пробовал это годами.
  3. Сервер выполняет первый шаг.
  4. Сервер записывает статус в поток ответов и сбрасывает.
  5. Повторяйте шаг (3) до завершения.

По сути, страница поддерживает соединение открытым до тех пор, пока задача не будет завершена, а периодическая очистка вывода предотвращает истечение времени ожидания клиента. Это может иметь проблемы с тайм-аутами и т. д., а конфигурация вашего сервера (буферизация вывода и т. д.) может быть проблемой.

Фоновая задача

Аналогично первому асинхронному подходу:

  1. Пользователь нажимает «Пуск»
  2. Сервер добавляет в БД строку, которая идентифицирует задачу для выполнения, извлекает идентификатор и возвращает его клиенту.
  3. Создайте запланированную задачу (скрипт, службу Windows и т. д.), которая опрашивает таблицу, выполняет нужные задачи и обновляет статус по мере выполнения.
  4. Клиент периодически повторно публикует форму с идентификатором БД. Сервер сверяет идентификатор с БД и возвращает сообщение о статусе (может включать информацию о предыдущих шагах, такую ​​как время выполнения, ETA и т. д.).
  5. Клиент переходит к (4) до тех пор, пока задача не будет завершена или не будут обнаружены ошибки.

Разница между этим и первым подходом заключается в том, что поток живет в отдельном процессе, а не в IIS.

Конечно, у каждого подхода есть свои проблемы, и может быть более простой способ сделать это.

person 3Dave    schedule 03.05.2011
comment
Спасибо, я думаю, что ваш полностью асинхронный подход без AJAX лучше всего. Раньше я устанавливал фоновые задачи и обнаружил, что они в лучшем случае нестабильны. - person ShaneH; 04.05.2011
comment
Дайте мне знать, как это происходит - у меня не было времени посмотреть, что происходит с потоком, когда он создается из страницы или контроллера. Однако я видел другие ссылки на него, которые указывают на то, что он должен работать. - person 3Dave; 04.05.2011