2014-04-03 75 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()方法。