пользователь нажмет страницу spawn.aspx который затем порождающее полдюжины потоков, рендеринг страниц с использованием всеспользование HttpContext по потокам
((System.Web.IHttpHandler)instance).ProcessRequest(reference to spawn's HTTPContext);
Не беспокойтесь о том, что ASP.Net, казалось бы, представляемый пользователь 7 ответов для 1 запроса, эта часть обрабатывается и отправляется только один ответ.
Проблема заключается в том, в среде с высоким трафиком (наша производственная Enviroment) с большим количеством нитей (счетверенных каре) мы получаем ошибку:
System.IndexOutOfRangeException at System.collections.ArrayList.Add at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, DateTime utcDepTime) at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, String requestVritualPath) at System.Web.UI.Page.AddWrappedFileDependencies(Object virtualFileDependencies) at ASP.spawned_page_no_1_aspx.FrameworkInitialize() at System.Web.UI.Page.ProcessRequest
Мы не можем дублировать его в другом месте. Мой коллега полагает, что это связано с тем, что я повторно использую оригинальный HTTPContext и передаю его в другие потоки, и что это не Thread-Safe.
Следуя этой логике, я попытался сделать новый HTTPContext для передачи в потоки. Но его части, похоже, «не сочетаются». В частности, мне нужно получить объект Session в новый HTTPContext. Я предполагаю, что хотел бы получить и другие части, такие как Cache. Для записи HTTPContext.Current.Session.IsSynchronized является ложным.
Мои вопросы:
- Как вы думаете, ошибка от использования HttpContext между потоками?
- Как это исправить?
- Если исправление дублирует HTTPContext для каждого потока, как я могу получить Session (и Cache) в новый? Запрос и ответ поступают в ctor, но сеанс не настраивается.
Edit: Подробнее
Так вернуться к этому утверждению: «Не беспокойтесь о том, что ASP.Net, казалось бы, представляемый пользователю 7 ответов 1 запрос, что часть обрабатывается и отправляется только один ответ ». Огромный поклонник Раймонда Чэня, я согласен с вами: «Теперь у вас есть две проблемы» - разумное утверждение в отсутствие дополнительной информации.
Что на самом деле происходит, так это то, что я создаю документ Excel для отправки назад. На странице spawn.aspx создается информация о состоянии, включая тот факт, что это рендеринг для excel, и объект для выполнения рендеринга. Каждая порожденная страница получает эту информацию и блокируется до тех пор, пока ее очередь не будет показана объекту. Если буквально выглядит следующим образом:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if (this.RenderToExcel)
{
Deadlocker.SpinUntilCurrent(DeadLockToken);
RenderReport(this, this.XLSWriter);
Deadlocker.Remove(DeadLockToken);
}
else
base.Render(writer);
}
Но вся обработка до этого момента - доступ к базе данных, управление иерархией, все это делается параллельно. И их много - достаточно, чтобы разделить его, все еще позволяя ему блокировать Render, сократит общее время в более чем половине.
И лучшая его часть - ничто не должно было быть переписано для рендеринга Excel. Все элементы управления знают, как сделать себя превосходными, и вы можете посещать каждую созданную страницу самостоятельно (это «нормальный случай» на самом деле - отчет о превосходстве - это всего лишь совокупность всех порожденных страниц.)
Итак, я понял, конечный результат должен был быть «вы не можете этого сделать, вам нужно переосмыслить подход», но мне пришлось хотя бы попробовать, потому что тот факт, что все работает так хорошо, не дублируя никакой логики или какого-либо кода или не абстрагируя ничего просто так совершенен. И это только многопоточность, вот в чем проблема, если я делаю страницы поочередно, все в порядке, просто медленно.
Al эта блокировка, вероятно, будет трудно устроить, исключение для потоковой передачи, которое он получает, относится к классу Page, который изменяет контекст http, если он не может переопределить действие на странице, которая делает это, и поместить блокировку, затем блокировка не будет работать. – meandmycode
Отличный комментарий, я согласен с вами. Мое предпочтение состояло бы в том, чтобы передать совершенно новый объект, который извлекает часть своей информации из контекста HTTP во время создания протектора. Это было бы доказательством пули. –