Многопоточность, HttpContext, длительная задача?

Недавно я начал работать с потоками Thread.Start() и длительными задачами и заметил несколько проблем, связанных с запросами.

ИЗМЕНИТЬ

Что бы вы предложили, чтобы предоставить пользователю обратную связь во время обработки задания, эффективно использовать пул потоков и, если возможно, использовать HttpContext?


person maxbeaudoin    schedule 24.07.2009    source источник
comment
Я в замешательстве, почему вы считаете, что HttpContext.Current не является потокобезопасным?   -  person Keith Adler    schedule 24.07.2009
comment
В основном это только для чтения, я считаю, что это потокобезопасно, но передача ссылки HttpContext в другой поток опасна, в конечном итоге срок действия истечет. Использование HttpContext в моих сборках опасно, а также всегда имеет значение null, если я решу использовать эти сборки в другом потоке без HttpContext.   -  person maxbeaudoin    schedule 24.07.2009


Ответы (3)


Вполне возможно, что вы допускаете ошибку при использовании потоков в приложении ASP.NET. Используете ли вы асинхронные страницы или используете новый Thread().Start? Последнее является ошибкой и может привести к некоторым проблемам с HttpContext, когда запрос выполнен, но поток все еще выполняется.

Пожалуйста, отредактируйте свой вопрос, чтобы дать более подробную информацию о том, что вы делаете с потоками.

person John Saunders    schedule 24.07.2009
comment
Спасибо. Вы совершаете ошибку. Длительные задачи не должны выполняться как часть веб-приложения. Их следует отправить в другую службу для исполнения. Инфраструктура ASP.NET не предназначена для решения длительных задач. - person John Saunders; 28.07.2009
comment
Что вы предлагаете, чтобы предоставить пользователю обратную связь во время обработки задания, эффективно использовать пул потоков и, если возможно, использовать HttpContext? - person maxbeaudoin; 29.07.2009
comment
Вы не можете предоставить отзыв для пользователя. Пользователь — это браузер. Браузер может использовать AJAX для запроса статуса операции. Вы не можете использовать HttpContext для этого. - person John Saunders; 29.07.2009
comment
Хорошо, скажем так, Пожалуйста, подождите... пока задание обрабатывается. Асинхр. страницы будут блокировать рендеринг нет!? - person maxbeaudoin; 29.07.2009
comment
Нет! Откуда вы черпаете эти идеи? А «Пожалуйста, подождите» просто делает видимым div. Он может даже содержать одну из тех крутых анимированных гифок, чтобы обмануть пользователя, заставив его думать, что что-то происходит. - person John Saunders; 29.07.2009
comment
Это каноническая статья об асинхронных страницах. Где вы видите, что это блокирует рендеринг? Слова блоки даже не появляются в статье. - person John Saunders; 29.07.2009
comment
Между моментом возврата Begin и вызовом End поток обработки запросов свободен для обслуживания других запросов, и до тех пор, пока не будет вызван End, рендеринг задерживается‹br /› Но я верю вам, если вы говорите, что у меня не будет белого загрузка страницы во время обработки длительной задачи. ;п - person maxbeaudoin; 29.07.2009
comment
Нет, я думал, что избавил вас от длительной задачи в ASP.NET. Задача не принадлежит ASP.NET. Вынесите это в отдельный сервис. Имейте запрос страницы для статуса завершения или прогресса и обновляйте пользовательский интерфейс AJAX на этой основе. Асинхронные страницы не предназначены для длительных задач. Они предназначены для задач, которые займут 2 секунды. Идея состоит в том, чтобы не привязывать рабочие потоки на 2 секунды, когда они будут просто заблокированы на 1,8 секунды. - person John Saunders; 29.07.2009
comment
Прости, что доставил тебе столько хлопот. Итак, веб-служба, обрабатывающая задачу, и каким-то образом класс состояния плюс пользовательский интерфейс AJAX? - person maxbeaudoin; 29.07.2009
comment
Если бы это было проблемой, я бы не был таким милым. :-) Я не имел в виду веб-сервис. Я имел в виду небольшую службу Windows. Общайтесь между ними с помощью WCF или MSMQ (предпочтительно WCF, размещенного в службе). Коммуникация просто передаст ему работу. Он может поддерживать список или даже очередь MSMQ выполненных запросов. Отдельный AJAX-вызов страницы будет запрашивать у службы статус. Может быть проще, если все, что вам нужно, это статус работы/выполнено/ошибка, а не подробности. - person John Saunders; 29.07.2009
comment
Я приму это как ответ ;p. Большое спасибо! - person maxbeaudoin; 29.07.2009

Для доступа к данным:

Для таких данных, как Server.Identity.Name, я думаю, что сбор этой информации заранее и передача ее вашему асинхронному коду — хороший подход. Его хорошая развязка, поскольку этот код теперь зависит только от этих нескольких свойств.

Для доступа к поведению:

Как вы используете потоки с ASP.NET? Работают два подхода: реализовать и зарегистрировать IAsyncHttpHandler или вызвать Page.AddOnPreRenderCompleteAsync() с какой-либо страницы ASP.NET.

Для IAsyncHttpHandler реализуемому вами обратному вызову передается HttpContext. Вы должны иметь возможность использовать этот ссылочный контекст из любого потока, пока вы не укажете ASP.NET, что обработка запроса завершена. Конечно, вы должны использовать эту ссылку только из одного потока за раз.

Для Page.AddOnPreRenderCompleteAsync должно быть безопасно вызывать Page.Context из ваших обратных вызовов при тех же условиях.

Для существующего кода в App_Code, который использует HttpContext.Current, вам необходимо реорганизовать его, чтобы код принимал HttpContext в качестве входного параметра. Существующий код может передаваться в HttpContext.Current, новый код, который вы пишете из потоков, может передаваться в одном из контекстов, описанных ранее в этом ответе.

person Frank Schwieterman    schedule 26.07.2009

Свойство HttpContext.Current объекта HttpContext является статическим. И его можно использовать в разных потоках или в сборках в App_Code. Но он возвращает объект HttpContext текущего запроса.

Все статические свойства HttpContext являются потокобезопасными. И все свойства экземпляра HttpContext не являются потокобезопасными.

person Pradeep Kumar    schedule 24.07.2009
comment
Результат HttpContext.Current зависит от того, в каком потоке вы находитесь, поэтому ваш совет неверен. - person Frank Schwieterman; 24.07.2009
comment
Обратите внимание, что я упомянул, но он возвращает объект HttpContext текущего запроса. Таким образом, если вы не находитесь в контексте запроса (за границей), HttpContext.Current, очевидно, вернет значение null независимо от того, в каком потоке вы находитесь. - person Pradeep Kumar; 24.07.2009