2013-05-01 5 views
2

У меня есть служба wcf (размещена в IIS), которая равна setup to use sessions. Кажется, это работает. Когда вызывается Application_PostAcquireRequestState, у меня есть идентификатор сеанса.Выполняет ли WCF сеанс более чем в одном потоке?

я в конечном итоге использовать его, как это (в моей Global.asax):

if (Context.Handler is IRequiresSessionState) 
{ 
    log4net.ThreadContext.Properties["sessionId"] = Session.SessionID; 
} 

Это, кажется, работает хорошо. Значение сохраняется в моем свойстве log4net.

Но когда начинается моя сервисная операция (мой фактический код службы WCF), свойство log4net равно null.

Поскольку свойство хранится в потоке (ThreadContext), я могу только предположить, что это означает, что сеанс настроен на один поток, а затем выполнен в другом потоке. Я прав?

В любом случае, чтобы получить свойство log4net, установленное на правильной нити (не забудьте сделать вышеуказанный вызов в начале каждой отдельной операции службы)?

+0

Я всегда ожидаю участия нескольких потоков. Я не знаю, где я это сделал. Вы изучали (обычай) поведение на службе, чтобы достичь того, чего хотите? – rene

ответ

1

Есть несколько сценариев, в которых WCF может изменить темы на вас:

  1. Global.asx нить не гарантированно использоваться для вызова службы (на самом деле его вряд ли).
  2. Если в течение одного сеанса имеется несколько вызовов, поток может также изменяться между вызовами одного и того же экземпляра службы.

В теории информация о состоянии, подобная этой, должна храниться в объекте Context Operation. Однако, поскольку log4net использует локальное хранилище потоков, он становится неудобным решением.

Есть в любом случае, чтобы получить мой log4net свойство устанавливается на на правильном нити (без необходимости помнить, чтобы сделать выше вызов в начале каждой отдельной операции службы)?

Да. Создайте заказ IOperationInvoker. Лучший пример, который я знаю, - Carlos Figueira's blog. Если вы применяете это как поведение службы, ваше свойство log4net всегда должно быть определено для кода службы.

Предупреждение: При добавлении в локальное хранилище потоков обязательно очистите. Вот почему log4net.ThreadContext.Stacks []. Push() возвращает IDisposable. Другими словами, ваш метод Invoke должен выглядеть (неполные и непроверенные): блог

public object Invoke(object instance, object[] inputs, out object[] outputs) 
{ 
    using (log4net.ThreadContext.Stacks[key].Push(value)) 
    { 
     return this.originalInvoker.Invoke(instance, inputs, out outputs); 
    } 
} 

знакомства Карлоса, чтобы понять, почему вы вызываете „originalInvoker“. Обратите внимание: если вы хотите поддерживать операции async, необходимые для реализации дополнительных методов.

2

Да, IIS может использовать несколько потоков для обслуживания нескольких запросов WCF. См. http://msdn.microsoft.com/en-us/library/cc512374.aspx для более подробной информации.

Возможно, вы захотите использовать разные экземпляры регистратора для каждого запроса WCF.

+0

Вы говорите «несколько потоков для обслуживания нескольких запросов WCF». Я говорю об одном вызове WCF ... (не несколько) – Vaccano

1

Пользовательские свойства не обязательно должны быть строками.Таким образом, вы можете хранить экземпляр следующего класса в глобальном контексте:

public class SessionIdProperty 
{ 
    public override string ToString() 
    { 
     // error handling omitted 
     return Session.SessionID; 
    } 
} 

Таким образом log4net может получить доступ к Session объекту непосредственно, когда он записывает сообщение. Log4net вызывает метод ToString() для свойств, отличных от строки.

 Смежные вопросы

  • Нет связанных вопросов^_^