55 votes

Où stocker les données pour l'appel en cours WCF? ThreadStatic est-il sûr?

Alors que mon service s'exécute, le nombre de classes qui auront besoin de l'accès de l'Utilisateur.Courant (c'est ma propre classe d'Utilisateur). Puis-je stocker en toute sécurité _currentUser en [ThreadStatic] variable? Ne WCF la réutilisation de ses fils? Si c'est le cas, quand est-ce que le nettoyage de la ThreadStatic de données? Si vous utilisez ThreadStatic est pas à l'abri, où dois-je mettre ces données? Est-il une place à l'intérieur de OperationContext.Actuelle où je peux stocker ce genre de données?

Edit 12/14/2009: je peux affirmer que l'utilisation d'un ThreadStatic variable n'est pas sûr. WCF fils sont dans un pool de threads et la ThreadStatic variable ne sont jamais réinitialisé.

90voto

Darin Dimitrov Points 528142

Il y a un blog post qui suggère de mettre en œuvre un IExtension<T>. Vous pouvez également prendre un coup d'oeil à cette discussion.

Voici une proposition de mise en œuvre:

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) { }
}

Que vous pourriez utiliser comme ça:

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

13voto

Sylvain Points 5439

EDIT: N'utilisez pas cette solution. Utilisez plutôt l'approche de Darin. Comme @ np-hard l'a dit, cette solution ne fonctionnera pas s'il existe des opérations asynchrones (la commutation de threads se produit).


J'ai trouvé une autre solution. Vous pouvez utiliser l'événement OperationCompleted de la classe OperationContext pour effacer vos variables ThreadStatic.

 public class SomeClass
{
    [ThreadStatic]
    private static _currentUser = null;

    public static void GetUser()
    {
        if ( _currentUser == null )
        {
            _currentUser = LoadUser();

            // Reinitialize _currentUser at the end of the request
            OperationContext.Current.OperationCompleted +=
                (sender, args) => _currentUser = null;
        }

        return _currentUser;
    }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X