我在IIS应用程序池中有一个WCF服务。 WCF服务的方法接收JSON中的某些数据,例如{“ object”:“ someobject”,“ payload”:[int key]}。
对于每个请求,我都运行新线程以使用key。
密钥添加到ConcurrentDictionary中,并锁定ConcurrentDictionary的值。
这样做的目的是:密钥的一个示例只能运行一次,例如:
线程1 -使用键1
运行
线程2 -使用键2
运行
线程3 -等待锁定线程1
但是,当我从ConcurrentDictionary中删除键时,另一个线程已经通过键获取了值并对其进行了处理。如何避免这种情况?
附近的线程处理程序示例
static ConcurrentDictionary<string, object> taskDictionary=new ConcurrentDictionary<string, object>();
static void ThreadHandler(int key)
{
try
{
var lockElem=taskDictionary.GetOrAdd(key, new object());
//Thread 3 get value by key 1 here and waits here
lock(lockElem)
{
taskDictionary.TryRemove(key, out _);
// but Thread 1 removes value by key 1 here
//and Thread 4 can add value in Dictionary with same key (key 1)
}
}
finally
{
}
}
在这种情况下,问题是:线程1使用GetOrAdd,然后锁定值,然后使用TryRemove。在这个时候,线程3使用GetOrAdd,获取值,但是等待线程1的锁。当线程1的锁释放时,线程3的锁删除了值。在这个时候,线程4使用GetOrAdd,并创建新的字典元素(与线程3的值不匹配)。并且我们有2个线程(线程3和线程4)使用相同的密钥。
答案 0 :(得分:0)
TryRemove函数已经为您提供了默认对象(如果它在词典中尚不存在),因此您可以简单地这样做:
static ConcurrentDictionary<int, object> taskDictionary=new ConcurrentDictionary<int, object>();
static void ThreadHandler(int key)
{
try
{
object obj;
// Remove object with key = 'key', or create a new object if it does not yet exist
taskDictionary.TryRemove(key, out obj);
// Do whatever you need to do with 'obj'
// Add the object (back) to the dictionary if necessary
taskDictionary.GetOrAdd(key, obj);
}
finally
{
}
}