Я просматриваю код службы WCF. В заголовке каждого сообщения мы вводим данные, которые служба будет использовать позже, чтобы построить строку подключения к БД. Это потому, что служба будет использоваться несколькими различными сайтами, каждая из которых имеет свою собственную БД, которую служба должна запрашивать. Мы используем расширяемость wcf. У нас есть собственный MessageInspector, который после получения запроса извлекает данные из заголовка сообщения, создает контекст (который реализует IExtension) и добавляет его в OperationContext.Current.Extensions. Перед отправкой ответа пользовательский контекст удаляется из коллекции Extencions.
Это довольно распространенный шаблон, как описано здесь:
Где хранить данные для текущего вызова WCF? Безопасен ли ThreadStatic?
и здесь:
Все это работает отлично, пока служба получает запрос, обрабатывает его, отправляет ответ и получает следующий запрос. Но что делать, если служба получает запрос и, прежде чем сможет ответить, получает второй запрос? Для его тестирования я создал небольшое консольное приложение. Я отправляю 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 не является потокобезопасным?