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也有一些问题。
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();
}
}
}
嗯,我读了一些文档,我不确定这是否是问题,但看起来你在这里有一个问题:
cacheLock.EnterReadLock();
try
{
//LockRecursionException here
_PrincipalMap[key] = Thread.CurrentPrincipal;
}
finally
{
cacheLock.ExitReadLock();
}
应该是cacheLock。EnterWriteLock和cacheLock。ExitWriteLock