我不得不在我的代码中使用并发字典,其中“键”是对象,“值”是表示唯一由第三方库提供给所述对象的连接参数。存储连接参数,就像通过第三方库引发事件时一样,唯一键是事件参数之一,通过该参数我们可以找到正确的对象来处理进一步的代码。ConcurrentDictionary中条目的分层锁定策略以及C#中的字典本身
我有问题如下:
偶尔并发字典需要与需要处理的对象的刷新列表进行更新。
单个对象在处理过程中需要锁,因为抛出的事件必须按顺序执行而不是并行执行。 (这是我们所看到的是,工作有时是在不同的线程并行处理,却得到了OptimisticConcurrencyException保存到数据库时,已成为近期要求)。
应用锁定到单个对象中字典不是问题,但是当我尝试从当前被锁定的字典中删除一个对象并刷新列表时出现新问题。我试过编写一个小的控制台应用程序,按顺序执行有问题的步骤,'Monitor.Exit(key);'行引发异常'对象同步方法是从一个非同步的代码块中调用的。'
class Program
{
static ConcurrentDictionary<object, int> _handles = new ConcurrentDictionary<object, int>();
static void Main(string[] args)
{
object lockableKey = 'key';
_handles.AddOrUpdate(lockableKey, 10, (oldkey, oldvalue) => 10);
var key = _handles.Keys.FirstOrDefault(h => h == lockableKey);
Console.WriteLine("key found, beginning to lock");
Monitor.Enter(key);
Console.WriteLine("key locked");
////Console.WriteLine("applying outer lock, hoping for code to stop executing");
////Monitor.Enter(_handles);
Console.WriteLine("Removing key from dictionary");
int dummy;
_handles.TryRemove(lockableKey, out dummy);
Console.WriteLine("Removing lock from object removed from dictionary");
Monitor.Exit(key);
}
所以现在的问题是,是否有申请锁定到就像一个主锁和等待所有儿童锁的对象字典内执行完刷新字典和继续之前外词典的方式处理传入的事件?
你的代码很混乱。您正在使用'lockableKey'(设置为“key”,应该用双引号引起)从字典中检索自己(意思是:'key'只能使用“key”或“null”值,因为您正在使用'FirstOrDefault')。然后你试图通过值“key”(或'null',它会抛出一个异常)来锁定。不能保证第一个“键”等于字典中的“键”;它们都可以是相同价值的不同参考。您正在从字典中删除“密钥”,然后尝试解锁。为什么不调用:'TryRemove(theKey)'开头? –
该示例不是实际实现的代码,而是更多的事件顺序的串行示例,正如我设想的那样(这将发生在不同的线程中)。这只是为了证明我面临的问题,我可能会遇到异常情况'对象同步方法是从一个未同步的代码块中调用的'。因此需要外锁和实际问题。 – sebpinski
你有没有想过在单个线程中执行字典更新的可能性?就像使用'Task.Factory.StartNew'重载创建单线程调度程序并在此调度程序上创建更新任务一样? – galenus