Как обновить сообщения о ходе выполнения при обработке данных в ASP.NET?

У меня есть процесс, который выводит пошаговые сообщения (т.е. Обработка элемента 1... Ошибка в элементе 2 и т.д. и т.д.).

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

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


person Danny    schedule 27.03.2010    source источник


Ответы (1)


Это не проблема с потоками, а проблема с пользовательским интерфейсом веб-браузера. Вы хотите, чтобы браузер отображал статус, когда вы работаете на сервере. Теоретически вы могли бы сделать что-то вроде:

Response.Write("something");
Response.Flush();

но Flush() не гарантирует, что браузер действительно отобразит ваш код в этот момент. На самом деле вы не можете контролировать, как данные кэшируются/разбиваются/буферизуются при передаче с сервера в браузер. Таким образом, каждое обновление должно быть «полной» http-транзакцией.

Один из самых распространенных способов — использовать для этого AJAX. Пользователь нажимает кнопку, которая запускает некоторую фоновую работу, и у вас есть таймер javascript, который опрашивает (делает запросы), чтобы проверить статус работы, и обновляет клиентский браузер.

Ознакомьтесь с индикатором выполнения в реальном времени с ASP.NET AJAX, чтобы узнать, как сделать индикатор выполнения ajax. с ajax и .net.

В этой статье есть отличный пример создания индикатора выполнения с помощью обработчика http: http://www.asp101.com/articles/matt/progressbar/default.asp

Чтобы доказать мою точку зрения, следующий код работает в Firefox, но не в IE или Chrome:

protected void Page_Load(object sender, EventArgs e)
{
    Response.Buffer = false;
    Response.Clear();
    Response.Write("<html><body>");
    Response.Write("1\n");
    Response.Flush();
    Thread.Sleep(2000);
    Response.Write("1\n");
    Response.Flush();
    Thread.Sleep(2000);
    Response.Write("1\n");
    Response.Flush();
    Thread.Sleep(2000);
    Response.Write("1\n");
    Response.Flush();
    Response.Write("</body></html>");
    Response.End();
}
person Mikael Svenson    schedule 27.03.2010
comment
Я видел действительно изящный способ, в котором раньше использовались потоки... Только не могу вспомнить, где и как это сделать. В основном запущен метод, и время от времени отображается следующее сообщение о ходе выполнения. - person Danny; 28.03.2010
comment
Ваша работа будет выполняться в потоке, который обновляет свое состояние выполнения. Затем ваш клиент будет опрашивать состояние. Но, как я уже упоминал, теоретически вы можете запустить работу в потоке и записать прогресс с помощью Response.Write и Response.Flush, но вы не гарантируете, что он действительно будет сброшен в браузер и отрендерен до завершения всего запроса. - person Mikael Svenson; 28.03.2010
comment
Я не думаю, что Response.Write работает в потоке. Тем не менее, что-то возвращается к элементу, который я видел раньше, и я думаю, что он мог использовать AJAX для объединения клиентской стороны статуса. - person Danny; 28.03.2010
comment
Добавлен пример кода, показывающий использование Flush и то, что он не будет работать во всех браузерах. Так что бросьте свою работу в фоновом потоке и попросите клиента опросить статус. Конечно, поток может умереть, если IIS повторно использует пул приложений, поэтому для 100%-ного решения длительная работа должна выполняться вне IIS в какой-либо службе. - person Mikael Svenson; 28.03.2010