Где хранить данные для текущего вызова WCF? ThreadStatic безопасно?

Пока мой сервис выполняется, многим классам потребуется доступ к User.Current (это мой собственный класс User). Могу ли я безопасно хранить _currentUser в [ThreadStatic] переменная? WCF повторно использует свои потоки? Если это так, когда он очистит данные ThreadStatic? Если использование ThreadStatic небезопасно, где я должен поместить эти данные? Есть ли место внутри OperationContext.Current, где я могу хранить такие данные?

Изменить 14/12/2009: я могу утверждать, что использование переменной ThreadStatic небезопасно. Потоки WCF находятся в пуле потоков, а переменная ThreadStatic никогда не инициализируется повторно.

3 ответа

Решение

Есть блог, который предлагает реализовать IExtension<T>, Вы также можете взглянуть на это обсуждение.

Вот предлагаемая реализация:

public class WcfOperationContext : IExtension<OperationContext>
{
    private readonly IDictionary<string, object> items;

    private WcfOperationContext()
    {
        items = new Dictionary<string, object>();
    }

    public IDictionary<string, object> Items
    {
        get { return items; }
    }

    public static WcfOperationContext Current
    {
        get
        {
            WcfOperationContext context = OperationContext.Current.Extensions.Find<WcfOperationContext>();
            if (context == null)
            {
                context = new WcfOperationContext();
                OperationContext.Current.Extensions.Add(context);
            }
            return context;
        }
    }

    public void Attach(OperationContext owner) { }
    public void Detach(OperationContext owner) { }
}

Что вы могли бы использовать так:

WcfOperationContext.Current.Items["user"] = _currentUser;
var user = WcfOperationContext.Current.Items["user"] as MyUser;

Альтернативное решение без добавления дополнительного класса.

    OperationContext operationContext = OperationContext.Current;
    operationContext.IncomingMessageProperties.Add("SessionKey", "ABCDEFG");

Чтобы получить значение

var ccc = aaa.IncomingMessageProperties["SessionKey"];

это оно

Я обнаружил, что мы пропускаем данные или текущий контекст, когда мы делаем асинхронный вызов с многопоточным переключением. Для обработки такого сценария вы можете попробовать использовать CallContext. Предполагается, что он будет использоваться в удаленном взаимодействии.NET, но он также должен работать в таком сценарии.

Установите данные в CallContext:

DataObject data = new DataObject() { RequestId = "1234" };
CallContext.SetData("DataSet", data);

Получение общих данных из CallContext:

var data = CallContext.GetData("DataSet") as DataObject;

// Shared data object has to implement ILogicalThreadAffinative

public class DataObject : ILogicalThreadAffinative
{
  public string Message { get; set; }
  public string Status { get; set; }
}

Почему ILogicalThreadAffinative?

Когда удаленный вызов метода выполняется для объекта в другом AppDomain, текущий класс CallContext генерирует LogicalCallContext, который перемещается вместе с вызовом в удаленное местоположение.

Только объекты, которые предоставляют интерфейс ILogicalThreadAffinative и хранятся в CallContext, распространяются за пределы AppDomain.

Другие вопросы по тегам