В приложении ASP.Net пользователь нажимает кнопку на веб-странице, после чего создается экземпляр объекта на сервере через обработчик событий и вызывается метод объекта. Метод передается во внешнюю систему для выполнения каких-либо действий, и это может занять некоторое время. Итак, что я хотел бы сделать, так это запустить этот вызов метода в другом потоке, чтобы я мог вернуть управление пользователю с помощью «Ваш запрос был отправлен». Я достаточно счастлив сделать это как «выстрелил и забыл», хотя было бы еще лучше, если бы пользователь мог продолжать опрашивать объект на предмет статуса.
Я не знаю, разрешает ли IIS мой поток продолжать работу, даже если срок сеанса пользователя истекает. Представьте, что пользователь запускает событие, а мы создаем экземпляр объекта на сервере и запускаем метод в новом потоке. Пользователь доволен сообщением «Ваш запрос отправлен» и закрывает свой браузер. В конце концов, этот сеанс пользователя истечет в IIS, но поток все еще может работать, выполняя работу. Будет ли IIS разрешать потоку продолжать работу или он убьет его и избавится от объекта по истечении пользовательского сеанса?
РЕДАКТИРОВАТЬ: Из ответов и комментариев я понимаю, что лучший способ сделать это - переместить длительную обработку за пределы IIS. Помимо всего прочего, это касается проблемы повторного использования домена приложения. На практике мне нужно запустить версию 1 за ограниченное время и работать внутри существующей структуры, поэтому я хотел бы избежать уровня обслуживания, отсюда и желание просто запустить поток внутри IIS. На практике «длительная работа» здесь будет составлять всего несколько минут, а параллелизм на веб-сайте будет низким, так что все должно быть в порядке. Но в следующей версии обязательно потребуется разделение на отдельный сервисный уровень.
Ответы:
Вы можете добиться того, чего хотите, но обычно это плохая идея. Некоторые механизмы блогов ASP.NET и CMS используют этот подход, потому что они хотят, чтобы их можно было установить в системе общего хостинга, а не зависеть от службы Windows, которую необходимо установить. Обычно они запускают длительный поток в Global.asax при запуске приложения, и этот процесс потока ставит задачи в очередь.
В дополнение к сокращению ресурсов, доступных IIS / ASP.NET для обработки запросов, у вас также есть проблемы с уничтожением потока при повторном использовании домена приложения, а затем вам приходится иметь дело с сохранением задачи, пока она находится в процессе выполнения, поскольку а также запуск резервной копии работы при восстановлении домена приложения.
Имейте в виду, что во многих случаях AppDomain перезапускается автоматически с интервалом по умолчанию, а также если вы обновляете web.config и т. Д.
Если вы можете справиться с персистентностью и транзакционными аспектами уничтожения вашего потока в любое время, то вы можете обойти повторное использование AppDomain, имея некоторый внешний процесс, который делает запрос на вашем сайте через некоторый интервал - так что если сайт будет переработан, вы гарантированно запустит его снова автоматически в течение X минут.
Опять же, это обычно плохая идея.
РЕДАКТИРОВАТЬ: Вот несколько примеров этой техники в действии:
Сервер совместной работы: использование служб Windows и фоновый поток для запуска кода через запланированные интервалы Создание фонового потока при первом запуске веб-сайта
РЕДАКТИРОВАТЬ (из далекого будущего) - в наши дни я бы использовал Hangfire .
источник
HostingEnvironment.RegisterObject
).QueueBackgroundWorkItem
для простой регистрации фоновых задач. Возможно, вы захотите обновить свой ответ еще раз.Я не согласен с принятым ответом.
Использование фонового потока (или задачи, начатой с
Task.Factory.StartNew
) в ASP.NET нормально. Как и во всех средах размещения, вам может потребоваться изучить средства, регулирующие завершение работы, и сотрудничать с ними.В ASP.NET вы можете зарегистрировать работу, которую необходимо корректно остановить при завершении работы, используя этот
HostingEnvironment.RegisterObject
метод. См. Эту статью и комментарии для обсуждения.(Как указывает Джерард в своем комментарии, теперь также есть
HostingEnvironment.QueueBackgroundWorkItem
вызов, чтобыRegisterObject
зарегистрировать планировщик для фонового элемента, над которым он будет работать. В целом новый метод лучше, поскольку он основан на задачах.)Что касается общей темы, о которой вы часто слышите, что это плохая идея, рассмотрите альтернативу развертыванию службы Windows (или другого типа приложения вне процесса):
Также обратите внимание, что в некоторых сложных сценариях может даже потребоваться, чтобы фоновый поток выполнялся в том же адресном пространстве, что и запросы. Я считаю тот факт, что ASP.NET может сделать это, большим преимуществом, которое стало возможным благодаря .NET.
источник
Вы не хотели бы использовать поток из пула потоков IIS для этой задачи, потому что это оставит этот поток неспособным обрабатывать будущие запросы. Вы можете изучить асинхронные страницы в ASP.NET 2.0 , но это тоже будет неправильным ответом. Вместо этого, похоже, вам было бы полезно изучить очередь сообщений Microsoft . По сути, вы должны добавить детали задачи в очередь, и другой фоновый процесс (возможно, служба Windows) будет отвечать за выполнение этой задачи. Но суть в том, что фоновый процесс полностью изолирован от IIS.
источник
Я бы предложил использовать HangFire для таких требований. Это приятный движок, работающий в фоновом режиме, поддерживает другую архитектуру, надежен, потому что поддерживается постоянным хранилищем.
источник
Здесь есть хорошая тема и пример кода: http://forums.asp.net/t/1534903.aspx?PageIndex=2
Я даже подумывал о том, чтобы вызвать на моем веб-сайте страницу поддержки активности из потока, чтобы поддерживать работу пула приложений. Имейте в виду, что если вы используете этот метод, вам нужна действительно хорошая обработка восстановления, потому что приложение может перезапуститься в любое время. Как многие уже упоминали, это неправильный подход, если у вас есть доступ к другим вариантам услуг, но для виртуального хостинга это может быть одним из ваших единственных вариантов.
Чтобы поддерживать пул приложений в рабочем состоянии, вы можете сделать запрос на свой сайт во время обработки потока. Это может помочь сохранить пул приложений в рабочем состоянии, если ваш процесс выполняется долго.
string tempStr = GetUrlPageSource("http://www.mysite.com/keepalive.aspx"); public static string GetUrlPageSource(string url) { string returnString = ""; try { Uri uri = new Uri(url); if (uri.Scheme == Uri.UriSchemeHttp) { HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uri); CookieContainer cookieJar = new CookieContainer(); req.CookieContainer = cookieJar; //set the request timeout to 60 seconds req.Timeout = 60000; req.UserAgent = "MyAgent"; //we do not want to request a persistent connection req.KeepAlive = false; HttpWebResponse resp = (HttpWebResponse)req.GetResponse(); Stream stream = resp.GetResponseStream(); StreamReader sr = new StreamReader(stream); returnString = sr.ReadToEnd(); sr.Close(); stream.Close(); resp.Close(); } } catch { returnString = ""; } return returnString; }
источник
Мы начали этот путь, и он действительно работал нормально, когда наше приложение находилось на одном сервере. Когда мы хотели масштабироваться до нескольких машин (или использовать несколько w3wp в веб-сервере), нам приходилось переоценивать и смотреть, как управлять очередью работы, обработкой ошибок, повторными попытками и сложной проблемой правильной блокировки, чтобы гарантировать только одну сервер подбирает следующий предмет.
... мы поняли, что не занимаемся написанием движков фоновой обработки, поэтому мы искали существующие решения и использовали потрясающий проект Hangfire OSS
Сергей Одиноков создал настоящую жемчужину, с которой действительно легко начать, и которая позволяет вам поменять бэкэнд, как сохраняется и ставится в очередь работа. Hangfire использует фоновые потоки, но сохраняет задания, обрабатывает повторные попытки и дает вам возможность видеть рабочую очередь. Таким образом, работа с зависанием надежна и выдерживает все капризы утилизации доменов приложений и т. Д.
В его базовой настройке в качестве хранилища используется sql-сервер, но вы можете заменить его на Redis или MSMQ, когда придет время масштабироваться. Он также имеет отличный пользовательский интерфейс для визуализации всех заданий и их статуса, а также позволяет повторно ставить задания в очередь.
Я хочу сказать, что, хотя в фоновом потоке вполне возможно делать то, что вы хотите, предстоит много работы, чтобы сделать его масштабируемым и надежным. Это хорошо для простых рабочих нагрузок, но когда ситуация становится более сложной, я предпочитаю использовать специально созданную библиотеку, а не прилагать усилия.
Чтобы получить более подробную информацию о доступных вариантах, посетите блог Скотта Хансельмана, в котором описаны несколько вариантов обработки фоновых заданий в asp.net. (Он дал Hangfire восторженный отзыв)
Также, как упоминает Джон, стоит прочитать блог Фила Хаака о том, почему этот подход проблематичен и как изящно остановить работу над потоком, когда домен приложения выгружается.
источник
Можете ли вы создать службу Windows для выполнения этой задачи? Затем использовать удаленное взаимодействие .NET с веб-сервера, чтобы вызвать службу Windows для выполнения действия? Если это так, я бы так и поступил.
Это устранит необходимость ретрансляции на IIS и ограничит часть его вычислительной мощности.
В противном случае я бы заставил пользователя сидеть там, пока процесс завершен. Таким образом вы убедитесь, что он завершен и не убит IIS.
источник
Похоже, что существует один поддерживаемый способ размещения длительной работы в IIS. Похоже, что для этого созданы службы рабочих процессов , особенно в сочетании с Windows Server AppFabric . Конструкция позволяет перезапускать пул приложений, поддерживая автоматическое сохранение и возобновление длительной работы.
источник
Вы можете запускать задачи в фоновом режиме, и они будут завершены даже после завершения запроса. Не позволяйте генерировать неперехваченное исключение . Обычно вы хотите всегда выбрасывать исключения. Если в новом потоке возникает исключение, это приведет к сбою рабочего процесса IIS - w3wp.exe , потому что вы больше не находитесь в контексте запроса. Это также приведет к уничтожению любых других фоновых задач, которые вы выполняете в дополнение к сеансам с поддержкой внутренней памяти, если вы их используете. Это сложно диагностировать, поэтому такая практика не рекомендуется.
источник
Просто создайте суррогатный процесс для выполнения асинхронных задач; это не обязательно должна быть служба Windows (хотя в большинстве случаев это более оптимальный подход. MSMQ - это больше, чем kill.
источник