В ASP.Net, как запустить код после отправки страницы

В ASP.Net я хочу запустить некоторый код (ведение журнала, прочая очистка) после того, как страница уже была отправлена ​​пользователю. Я не хочу, чтобы этот код влиял на количество времени, необходимое клиенту для получения ответа. Я попытался разместить этот код в части страницы OnUnload, но при тестировании (с использованием точек останова или циклов ожидания) клиент фактически не отображает страницу до тех пор, пока код в OnUnload не завершит выполнение. Несмотря на то, что на данный момент объект ответа больше не доступен, и поэтому я предполагаю, что буферизованный ответ был отправлен клиенту, клиент по-прежнему не отображает страницу до тех пор, пока выполнение OnUnload не завершится. Единственный способ, который кажется работающим на данный момент, - это запустить новый поток для выполнения работы и позволить OnUnload немедленно завершиться. Однако я не знаю, безопасно это или нет. Будет ли сервер убивать поток, если он выполняется слишком долго после того, как страница уже отправлена? Есть ли более правильный способ сделать это?


person Kibbee    schedule 25.08.2010    source источник
comment
Можете ли вы использовать очередь сообщений и сделать так, чтобы об этом позаботился фоновый процесс? Больше похоже на то, как веб-роль и рабочая роль должны взаимодействовать друг с другом в Azure?   -  person Roopesh Shenoy    schedule 25.08.2010
comment
Я пытался помочь проголосовать против, но похоже, что кому-то ДЕЙСТВИТЕЛЬНО не нравится этот вопрос!   -  person mclark1129    schedule 25.08.2010
comment
Я обычно удаляю вопросы, если они слишком долго остаются без ответа. Обычно вы не получите его позже, и это помогает ограничить количество неотвеченных (и, по сути, бесполезных) вопросов от SO.   -  person mclark1129    schedule 26.08.2010
comment
Какая уборка? Помогут ли асинхронные страницы? msdn.microsoft.com/en-us/magazine/cc163725.aspx# S2   -  person Greg    schedule 26.08.2010


Ответы (7)


Кибби,

Попробуйте переопределить метод Page.Render и сбросить ответ следующим образом:

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
    MyBase.Render(writer)

    Response.Flush() ' Sends all buffered output to the client

    ' Run some code after user gets their content
End Sub

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

HTH,

Майк

person mclark1129    schedule 25.08.2010
comment
Это сработало, как и ожидалось. Имея доступный объект Repsonse, я смог заставить браузер получать и отображать контент. Однако проблема в том, что страница браузера по-прежнему отображается как загружаемая (вращающийся значок / песочные часы), как при загрузке страницы, даже после того, как контент был получен. Это поведение сохранялось даже после того, как я добавил Response.Close после Response.Flush (). Также приятно видеть кого-то еще, кто кодирует в VB.Net. Кажется, большая часть материалов о .Net здесь сосредоточена на C #. - person Kibbee; 26.08.2010
comment
Я почти уверен, что ответ не завершится полностью, пока не завершится выполнение всего жизненного цикла ASP.net. Это включает событие HttpApplication.EndRequest, AFIAK которого является последней точкой в ​​жизненном цикле (не считая, конечно, момента завершения приложения). Я думаю, что приведенный выше метод будет наиболее близким к тому, что вы хотите, без создания нового потока. Если вы используете многопоточность, я предлагаю создать поток в HttpApplication.EndRequest, чтобы избежать прерывания потока на Response.End (). - person mclark1129; 26.08.2010

Выгрузка - это последняя часть жизненного цикла страницы ASP.NET. См. Ссылку ниже:

http://msdn.microsoft.com/en-us/library/ms178472.aspx

Можно ли это сделать с помощью javascript или AJAX?

person Abe Miessler    schedule 25.08.2010
comment
Я специально заявил, что пытался использовать раздел «Выгрузка», но браузер по-прежнему не отображает страницу, пока не будет выполнен код выгрузки. Это не то, что я мог бы сделать в Javascript или Ajax, потому что он должен работать на стороне сервера, и я не могу зависеть от того, что у клиента включен Javascript для вызова AJAX для запуска процесса. - person Kibbee; 25.08.2010
comment
Кибби Я читал это, но вы не заявили, что знаете, что это последний этап жизненного цикла страницы, поэтому я упомянул об этом. Я не думаю, что он заслуживает -1, но я обязательно не буду публиковать какие-либо из ваших вопросов в будущем, если вы собираетесь обвинить меня в том, что я пытаюсь помочь вам понять, как работает asp.net. - person Abe Miessler; 25.08.2010
comment
Извините, но я чувствовал, что описание отрицательного голоса. Этот ответ бесполезен, но здесь он не применяется. Лично я считаю, что если вы на самом деле не предоставляете информацию, которая может решить проблему, вам следует оставить ее в качестве комментария. Ответ, который вы дали, - это просто дополнительная информация. Это вообще не решает мою проблему. - person Kibbee; 25.08.2010

Как насчет подключения к событию page.Disposed вместо события Unload?

person Shawn de Wet    schedule 25.08.2010
comment
Пробовал это. Похоже, что пока страница отправляется до выполнения кода, проблема, с которой я сейчас сталкиваюсь, заключается в том, что, похоже, код вообще не работает. Хотя он может работать в будущем, когда сам объект будет удален. Я хотел бы, чтобы код выполнялся более своевременно, а не тогда, когда доходит до удаления объекта. - person Kibbee; 25.08.2010

В зависимости от того, что вам нужно сделать, может быть создан фильтр ISAPI, чтобы делать что-то в конце ответа.

person SargeATM    schedule 25.08.2010

Вы можете попробовать это решение - Лучшая реализация фоновой службы ASP.NET

Использование службы Windows и взаимодействие с ней через MSMQ может быть гораздо более надежным решением и лучше масштабируется. Это поможет вам разделить проблемы и позволить интерфейсу asp.net просто сосредоточиться на пользователе, в то время как служба Windows сосредоточится на фоновых задачах.

Если вы переходите в облако с помощью Azure, вы можете просто заменить интерфейс asp.net на веб-роль, а службу Windows на рабочую роль, и решение ur можно легко масштабировать!

person Roopesh Shenoy    schedule 26.08.2010

Вот способ сделать это деревенщиной. Имейте вторую страницу aspx, которая выполняет всю вашу логику «очистки» пост-рендеринга. Назовите его, например, «cleanup.aspx». Запустите код очистки в Page_Load файла cleanup.aspx:

public partial class cleanup: System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e) 
    {
        // do logging blah blah here....
    }
}

На главной странице aspx имейте функцию JavaScript, которая выполняет вызов AJAX для cleanup.aspx. Включите функцию AJAX после загрузки страницы. Я рекомендую jquery, в таком случае ваш код будет выглядеть так:

$(function(){
    yourAJAXYFunctionName();
});

function yourAJAXYFunctionName()() {
 // ajax code here
 //  
 $.ajax({
   url: "cleanup.aspx",
  });
}

Таким образом, запускается код вашей первой страницы, а затем страница отправляется в браузер. Когда страница отображается для клиента, вторая страница ASPX вызывается через AJAX, что на самом деле не имеет значения для cleanup.aspx, ее не волнует, как она вызывается и выполняется событие загрузки страницы. Затем запускается ваш код очистки / ведения журнала.

Предостережения: необходим клиентский JavaScript. Но на самом деле, у кого, черт возьми, вообще нет JS? Кроме того, ваша страница cleanup.aspx полностью абстрагирована от вашей главной страницы, поэтому, если вы хотите использовать какой-либо объект в cleanup.aspx, созданный на вашей первой странице, вам придется сохранить их в сеансе или файлах cookie, или вы можете передать их как параметры в вызове AJAX. Это потребует динамических манипуляций с самим сценарием AJAX, но это не слишком сложно.

person Graham    schedule 24.02.2011

Лучше я думаю попробуйте попробовать {Response.End ()} catch {} runcode ();

person in4man    schedule 21.08.2014
comment
На самом деле это не ответ в его текущем состоянии. Пожалуйста, переформатируйте. - person simonmorley; 22.08.2014