2015-01-18 4 views
4

Как вы знаете, HttpContext.Current возвращает текущий контекст в конвейере приложения.
Также это свойство static, поэтому логически любые изменения в этом или его свойствах должны влиять на другие конвейеры.Как HttpContext.Current работает по каждому запросу в конвейере IIS?

Статическое поле идентифицирует ровно одно место для хранения. Независимо от того, как создано множество экземпляров класса, существует только одна копия статического поля . More

Как IIS справиться с этим, чтобы предотвратить конфликт на других трубопроводах и каждый HttpContext.Current быть уникальным на каждом конвейере?

Например, для двух пользователей, которые уже вошли в систему, HttpContext.Current.User.Identity.Name дает имя пользователя, отправившего запрос на сервер.

ASP.NET Pipeline:
enter image description here

ответ

7

Current является собственностью, а не поле, так что это статический метод на самом деле.

Этот метод может возвращать разные экземпляры для разных потоков, и это действительно так.

Если вы разрабатываете многопоточное веб-приложение, имейте в виду несколько вещей.

  1. Не использовать ThreadStaticAttribute. Он работает в Windows и консольных приложениях, но может не работать в веб-приложениях, поскольку один запрос может обрабатываться разными потоками, если вы используете async, await и Task<T>.

  2. Использовать HttpContext.Current.Items вместо ThreadStaticAttribute. Эти Items являются «статическими» в каждом HttpContext.

  3. Использование SynchronizationContext если вам нужны важные параметры HttpContext (региональные настройки, пользователь вошедший, и свой собственный HttpContext.Items) после асинхронных вызовов (если вы не используете await).

Причина, по которой вы должны быть осторожны, это пул потоков. Вполне возможно, что ваш асинхронный метод запускается в первом потоке, продолжается через секунду и заканчивается на третьем. Поскольку каждый поток имеет свою собственную копию статического поля потока, вы можете получить непредсказуемые различные значения поля в разных местах вашего метода. SynchronizationContext позволяет вам вернуться к исходному потоку с правильными значениями региональных настроек, HttpContext.Items и т. Д. Оператор await работает для вас, поэтому вам не нужно заботиться о контексте, если вы используете await (благодаря @StephenCleary для коррекции).

Теперь для потоков-статических полей. Когда ASP.NET получает HTTP-запрос, он создает новый экземпляр HttpContext с пустой коллекцией HttpContext.Items. В то же время поля ThreadStatic инициализируются уже предыдущим HTTP-запросом. Поэтому f.e. a Singleton класс, основанный на потоковом поле, может работать неправильно.Это важно как в синхронных, так и в асинхронных методах веб-приложения.

+0

Нет необходимости явно использовать 'SynchronizationContext'; 'await' будет делать это автоматически по умолчанию. –

+0

Спасибо. Похоже, я немного параноик. Я исправлю свой ответ. –

+0

@MarkShevchenko Но я не могу найти какой-либо атрибут ThreadStatic, используемый внутри файла HttpContext.cs. Где это на самом деле используется ?! – rejnev

4

Ответ лежит на локальном хранилище потоков, реализованном с помощью ThreadStatic в .NET. Здесь также применим шаблон дизайна окружающего контекста.

+2

За исключением того факта, что 'HttpContext.Current', похоже, не использует этот атрибут - его реализация кажется значительно более сложной. –

+0

Конечно, свойство не может напрямую ссылаться на ThreadStatic, только поля. Но там должно быть поточно-локальное хранилище где-то внутри его реализации. – fejesjoco