2014-04-03 77 views
2

我的代码抛出一个参数异常,抱怨“具有相同密钥的项目已被添加。”
我锁定了抱怨的对象,所以我不知道如何在另一个线程上更新它。
WaypointIconDictionary是静态的。
下面是代码字典添加()例外锁定字典

try 
{ 
    lock (WaypointIconDictionary) 
    { 
     if (!WaypointIconDictionary.ContainsKey(waypoint.TypeOfWaypoint)) 
     { 
      var thisIcon = waypoint.Icon; 
      var index = IconCache.LoadIcon(thisIcon, thisIcon.Width/2, thisIcon.Height); 
      WaypointIconDictionary.Add(waypoint.TypeOfWaypoint, index); 
     } 
     IconCache.DrawIcon(graphics, x, y, WaypointIconDictionary[waypoint.TypeOfWaypoint], false); 
    } 
} 
catch (Exception ex) 
{ 
    Logger.Error("Waypoint drawing {0}", ex.Message); 
} 
+1

您应该锁定在不同的对象上,同时查看['ConcurrentDictionary '](http://msdn.microsoft.com/zh-cn/library/dd287191(v = vs.110).aspx)for multi线程应用程序 – user2711965

+2

“我不知道它是如何在另一个线程上更新的。”也许其他更新来自不锁定的方法?.. – dasblinkenlight

+0

锁应该是私有静态的,试图创建一个专用锁对象:private static readonly Object lockKey = new Object(); – WhoIsRich

回答

1

这可能不是一个锁定问题:它可能是你实际上试图添加相同的密钥两次。

如果你是绝对肯定,这就是新的条目添加到字典中的唯一的地方,这个例外只能由引起:

  1. waypoint被另一个线程被覆盖
  2. IconCache.LoadIcon有令人讨厌的副作用,导致此线程再次调用此方法。

单步执行代码或记录要添加的内容,以便知道发生了什么。

+0

好点,我甚至没有想到这一点。 –

+0

但这就是为什么我先检查 - 这就是要点! – DefenestrationDay

+0

我添加了两件事你可以/应该检查我的答案。你能告诉我们声明路点变量的代码吗? –

1

不要锁定WaypointIconDictionary,创建新的对象有锁定,比如唯一的目的:

Object _locker = new Object(); 

,然后在该锁:

lock (_locker) 
{ 

同时检查WaypointIconDictionary的所有用法,并确保没有其他任何东西添加到它。最好的办法是将WaypointIconDictionary包装在一个对象中,以便所有对它的调用都可以集中并锁定。

看看你的示例,如果WaypointIconDictionary是静态的,你将不得不使静态_locker。

另一种选择是使用ConcurrentDictionary,然后使用TryAdd()方法。