多线程Web服务访问和修改List对象而不是线程安全

时间:2011-08-25 15:26:59

标签: c# multithreading

当我的多线程应用程序修改同一个对象并且List对象无法处理两个线程在同一时间向列表添加对象时,我学到了很多困难。

我做了一些研究,发现我可以使用锁来避免这种情况发生,在应用程序运行一个月后,即使锁定对象就位也会再次发生。我不明白这仍然是怎么发生的。 错误消息与以前相同: 1-源阵列不够长。检查srcIndex和length,以及数组的下限。 2-索引超出了数组的范围。

在类私有成员中我有这个成员变量

private static readonly object _syncLock = new object();

在公共职能部门

public Dictionary<int, QueuedLetter> GetXMLFragment(Dictionary<int, QueuedLetter> queuedLetters, GroupNode GroupNode, GroupNode ParentGroupNode, StoredProcedure storedProcedure)

这是我使用_synclock对象的代码行如下

XmlFragment xf = new XmlFragment();
xf.Fragment = xe;
xf.LetterQueueOID = lq.LetterQueueOID;
xf.ParentGroupNodeName = ParentGroupNodeName;
xf.LinkingField = GroupNode.LinkingField;
xf.GroupNodeName = GroupNode.GroupNodeName;

lock (_syncLock)
{
   if (lq.Fragments == null)
      lq.Fragments = new List<XmlFragment>();
   lq.Fragments.Add(xf);
}

我使用一个线程池在另一个类中创建多线程功能,它在同一个类中调用一个启动函数,就像锁定发生在上面一样

events[i] = new AutoResetEvent(false);
AttachFragments f = new AttachFragments(events[i], groupNodeOID, QueuedLetters, string.Format("Failed while fragment Data : {0}, was executing ", groupNodeName));
f.OnException += ThreadErroredOut;
ThreadPool.QueueUserWorkItem(new WaitCallback(f.UpdateFragments));

如果你能就我做错的事情给我一些建议,我将不胜感激。

我考虑过使用 .NET 4.0中的线程安全集合http://msdn.microsoft.com/en-us/library/dd997305.aspx 但是我没有使用过它,如果我把它改成这个,这将导致代码发生重大变化,这需要Q.A.进行更深入的测试。队。

两个例外的堆栈跟踪: 1-源阵列不够长。检查srcIndex和length,以及数组的下限:    System.Aolray.Copy(Array sourceArray,Int32 sourceIndex,Array destinationArray,Int32 destinationIndex,Int32 length,Boolean reliable),位于System.Collections.Generic.List 1.Insert(Int32 index, T item) at JE.ThunderHead.Business.AttachFragments.GetXMLFragment(Dictionary 2 queuedLetters,GroupNode GroupNode,GroupNode ParentGroupNode,StoredProcedure storedProcedure)在C:\ TFS \ LMS \ Release \ LM_05 \ LM_05.01 \ Solutions \ ThunderHead \ JE.Thunderhead.Business \ AttachFragments.cs:第135行,位于C:\中的JE.ThunderHead.Business.AttachFragments.UpdateFragments(Object stateinfo) TFS \ LMS \ Release \ LM_05 \ LM_05.01 \ Solutions \ ThunderHead \ JE.Thunderhead.Business \ AttachFragments.cs:第99行

2-索引超出了数组的范围:    at System.Collections.Generic.List 1.Add(T item) at JE.ThunderHead.Business.AttachFragments.GetXMLFragment(Dictionary 2 queuedLetters,GroupNode GroupNode,GroupNode ParentGroupNode,StoredProcedure storedProcedure)在C:\ TFS \ LMS \ Release \ LM_05 \ LM_05.01 \ Solutions \ ThunderHead \ JE.Thunderhead.Business \ AttachFragments.cs:第231行

2 个答案:

答案 0 :(得分:3)

从您发布的堆栈跟踪中,看起来该列表中有Insert您没有在此处显示。如果是这种情况,您需要使用相同的锁定对象锁定Insert

答案 1 :(得分:1)

我可以肯定地说,您展示的代码段不会同时更新lq

如果没有更多的代码,我不能告诉你更多。最好将子类lq子类化,并将锁定放在该实现中。之后,我可以确定lq是线程安全的。

我认为您应该考虑重构以按照您的建议使用ConcurrentQueue<T>。尽管Q.A.的费用。循环可以确保质量和联锁操作和螺纹纺纱的潜在性能改进。