WCF Operation.Context not Thread safe?
Я просматриваю код службы WCF.
В заголовке каждого сообщения мы вводим данные, которые служба будет использовать позже, чтобы построить строку подключения к БД.
Это потому, что служба будет использоваться несколькими различными сайтами, каждая из которых имеет свою собственную БД, которую служба должна запрашивать.
Мы используем расширяемость wcf. У нас есть собственный MessageInspector, который после получения запроса извлекает данные из заголовка сообщения, создает контекст (который реализует IExtension) и добавляет его в OperationContext.Current.Extensions.
Перед отправкой ответа пользовательский контекст удаляется из коллекции Extencions.
Это довольно распространенный шаблон, как описано здесь:
Где хранить данные для текущего вызова WCF? Безопасен ли ThreadStatic?
и здесь:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/319cac66-66e8-4dfe-9a82-dfd289c9df1f/wcf-doesnt-have-session-storage-so-where-should-one-store-call-specific-data?forum=wcf
Все это работает отлично, пока служба получает запрос, обрабатывает его, отправляет ответ и получает следующий запрос.
Но что делать, если служба получает запрос и, прежде чем сможет ответить, получает второй запрос? Для его тестирования я создал небольшое консольное приложение. Я отправляю 2 сообщения из 2 разных потоков, я заставил службу wcf ждать в течение 2 секунд, чтобы гарантировать, что второй запрос поступит до того, как первый будет завершен, и это то, что я получаю:
Идентификатор сайта: test1450; Сессия: uuid: 2caf47cf-7d46-4d72-9275-d9c037fa0e70; id = 2: Идентификатор потока: 6
Идентификатор сайта: test1450; Сессия: uuid: 2caf47cf-7d46-4d72-9275-d9c037fa0e70; id = 3: Идентификатор потока: 22
Похоже, wcf создает 2 сеанса, выполняющихся на 2 разных потоках, но идентификатор сайта одинаковый. Это не должно. Судя по этому, это выглядит как OperationContext.Current.Extensions - это коллекция, совместно используемая между потоками.
Прямо сейчас я склонен думать, что мой тест ошибочен, и я что-то пропустил.
Кто-нибудь пробовал что-то подобное и выяснил, что OperationContext.Current не является потокобезопасным?
Ответы
Ответ 1
OperationContext.Current, как и другие аналогичные свойства, такие как HttpContext.Current, имеют потоковые аффинные (или статические) значения. Таким образом, они являются потокобезопасными в том смысле, что несколько потоков могут их читать, но разные потоки получат разные экземпляры. Их можно рассматривать как словари между конкретными потоками и экземплярами.
Итак, в этом контексте они не являются потокобезопасными.
Запросы обслуживаются пулом потоков, поэтому одновременные запросы будут иметь разные идентификаторы потоков. (до точки, где пул потоков заполнен, запросы будут помещены в режим ожидания)