Вопрос

У меня есть веб-служба ASP.NET, которая выполняет некоторую тяжелую работу, например, некоторые файловые операции или генерирует таблицы Excel из набора кристаллических отчетов.Я не хочу, чтобы меня заблокировали при вызове этой веб-службы, поэтому я хочу сделать вызов веб-службы асинхронным.Кроме того, я хочу вызвать этот веб-сервис с веб-страницы и мне нужен какой-то механизм, который позволит мне продолжать опрашивать сервер, чтобы я мог отображать на экране какой-то индикатор прогресса, например, количество файлов, которые были обработаны.Обратите внимание, что мне не нужно уведомление о завершении вызова веб-метода, а скорее, мне нужен статус выполнения в реальном времени.Как мне это сделать?

Это было полезно?

Решение

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

Например.в стиле REST вы можете сделать запрос GET для http://yourserver.com/app/jobstatus/4133/ который вернет простое число «52» как text/plain.Тогда вам просто нужно запрашивать это каждую (секунду?две секунды?десять секунд?), чтобы увидеть, как далеко это продвинулось.

То, как вы на самом деле осуществляете мониторинг на бэкэнде, во многом зависит от того, что представляет собой ваш процесс и как он работает.

Другие советы

Я думаю, что веб-служба XML работает медленно, поэтому создаю несколько методов и опрос прогресс будет очень медленно и создаст огромную нагрузку на сервер.Я бы не стал делать это в производственной среде.Я вижу те же (но меньшие) проблемы с опросом базы данных.

Пытаться SOAP-расширения вместо.Он реализует событийно-ориентированную модель.Видеть Добавление индикатора выполнения в клиентское приложение веб-службы на MSDN.

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

Позволяет сделать что-то подобное в вашем клиенте:

//...
private localhost.MyWebServiceService _myWebService = new localhost.MyWebServiceService ();
_myWebService.processDelegate += ProgressUpdate;
_myWebService.CallHeavyMethod();
//...

private void ProgressUpdate(object sender, ProgressEventArgs e)
{
  double progress = ((double)e.ProcessedSize / (double)e.TotalSize) * 100.00;
  //Show Progress...
}

Попросите первоначальный вызов веб-службы «начать создание отчета» создать задачу в некотором пуле задач и вернуть вызывающей стороне идентификатор задачи.

Затем предоставьте другой метод, который возвращает «процент выполнения» для данного идентификатора задачи.

Предоставьте третий метод, который возвращает фактический результат выполненной задачи.

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

Заставьте веб-сервис возвращать какой-то идентификатор задачи или идентификатор сеанса.Создайте еще один веб-метод для запроса с этим идентификатором, который возвращает необходимую информацию (% завершения, список файлов и т. д.).Опрашивайте этот метод через некоторый интервал времени от клиента.

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

РЕДАКТИРОВАТЬ:Я только что увидел еще один похожий ответ и прокомментировал его.Комментатор прав: вы можете использовать таблицу в памяти, чтобы избежать дисковых операций, но при этом использовать отдельный сервер БД.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top