JQuery并发问题与WCF自定义端点行为中的字典

本文关键字:字典 端点 自定义 并发 问题 WCF JQuery | 更新日期: 2023-09-27 18:04:04

我将尽我所能解释这一点。如果我不喜欢这个,我就删除这个,然后继续。也许你们可以给我一些建议。

这是一个web应用程序。(c# 4.0(服务器)和JQuery 1.6.1客户端)

在客户端,我们设置了一堆文本框,当.focusout事件被触发时,一个AJAX调用被触发,将数据发送到WCF服务。

在服务器端,我们已经创建了一个自定义端点行为,因为我们已经设置了一些安全的东西,所以我们可以在这些AJAX调用时抓取用户信息(这对我们来说很好,所以我不寻找安装帮助。)

问题来了,当我得到创造性的JQuery,就像如果我想告诉一堆框一次更新(即使它是2个文本框!)

$(".blahblahClass").focusout(); //fires a bunch of AJAX calls

。我得到了一个系统。IndexOutOfRangeException(假设是一个线程错误)在我的JsonAuthCallContextInitializer下面,在这里,它试图在我的CallContextInitializer的BeforeInvoke()中添加一个键到这个字典:

_PrincipalMap[key] = Thread.CurrentPrincipal;

重要的是,我要从AfterInvoke()

中的这个字典中删除一个键。

好吧. .作为一个字典,这可能不是线程安全的。所以我添加了一些lock s(你将在下面的代码中看到)

我去了ReaderWriterLockSlim,因为我读到lock有一些并发问题,ReaderWriterLock也有一些问题。

所以我添加了锁(它们在下面的代码中),使用默认的LockRecursionPolicy(这意味着我只是让ReaderWriterLockSlim构造函数为空)。

当我再次运行应用程序时,我会得到一个LockRecursionException(在这种模式下,读锁可能无法获得写锁)

LockRecursionPolicy.SupportsRecursion扔进ReaderWriterLockSlim构造函数使异常消失,不幸的是,不是所有的文本框在我的网页更新..

在我的脑海中(我今天将尝试)也许是使字典本身线程安全。像这样的问题:实现线程安全字典的最佳方式是什么?

但我不相信它能解决这里的问题。

更新:所以我尝试了一些其他的事情。我决定使用ConcurrentDictionary,我甚至决定了什么,并在AfterInvoke()中去掉了。remove。不行。它基本上要么抑制错误,只有一个文本框在。html页面将更新,或在BeforeInvoke()中失败,如果你有超过几个文本框更新

供参考,静态字典是有意的

建议吗?(适用行为准则如下)

        public class JsonAuthEndpointBehavior : IEndpointBehavior
        {
            private string _key;
            public JsonAuthEndpointBehavior(string key)
            {
                if (key == null) throw new ArgumentNullException("key");
                _key = key;
            }
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
            {
                var jsonAuthCallContextInitializer = new JsonAuthCallContextInitializer(_key);
                foreach (var operation in endpointDispatcher.DispatchRuntime.Operations)
                {
                    operation.CallContextInitializers.Add(jsonAuthCallContextInitializer);
                }
            }
            protected void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                // Do nothing
            }
            public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
            {
                // Do nothing
            }
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                // Do nothing
            }
            public void Validate(ServiceEndpoint endpoint)
            {
                // Do nothing
            }
        }

  public class JsonAuthCallContextInitializer : ICallContextInitializer
    {
        private readonly string _key;
        private static readonly Dictionary<int, IPrincipal> _PrincipalMap = new Dictionary<int, IPrincipal>();
        private readonly ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
        public JsonAuthCallContextInitializer(string key)
        {
            if (key == null) throw new ArgumentNullException("key");
            _key = key;
        }
        public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
        {
            if (WebOperationContext.Current == null)
                throw new NotSupportedException("JSON Authentication call context initializer requires HTTP");
            if (Thread.CurrentPrincipal != null)
            {
                var key = Thread.CurrentThread.ManagedThreadId;
                cacheLock.EnterReadLock();
                try
                {
                    //LockRecursionException here
                    _PrincipalMap[key] = Thread.CurrentPrincipal;
                }
                finally
                {
                    cacheLock.ExitReadLock();
                }
            }
            Thread.CurrentPrincipal = new ClaimsPrincipal(new[]
            {
                new ClaimsIdentity((from c in x.Claims select new Claim(blahblah.ToString())).ToArray())
            });
            return null;
        }
        public void AfterInvoke(object correlationState)
        {
            var key = Thread.CurrentThread.ManagedThreadId;
               cacheLock.EnterReadLock();
               try
               {
                   if (!_PrincipalMap.ContainsKey(key)) return;
                   Thread.CurrentPrincipal = _PrincipalMap[key];
               }
               finally
               {
                   cacheLock.ExitReadLock();
               }
               cacheLock.EnterWriteLock();
               try
               {
                    _PrincipalMap.Remove(key);
               }
               catch (Exception)
               {
                   cacheLock.ExitWriteLock();
               }
         }
    }

JQuery并发问题与WCF自定义端点行为中的字典

嗯,我读了一些文档,我不确定这是否是问题,但看起来你在这里有一个问题:

            cacheLock.EnterReadLock();
            try
            {
                //LockRecursionException here
                _PrincipalMap[key] = Thread.CurrentPrincipal;
            }
            finally
            {
                cacheLock.ExitReadLock();
            }

应该是cacheLock。EnterWriteLock和cacheLock。ExitWriteLock