当我的多线程应用程序修改同一个对象并且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行
答案 0 :(得分:3)
从您发布的堆栈跟踪中,看起来该列表中有Insert
您没有在此处显示。如果是这种情况,您需要使用相同的锁定对象锁定Insert
。
答案 1 :(得分:1)
我可以肯定地说,您展示的代码段不会同时更新lq
。
如果没有更多的代码,我不能告诉你更多。最好将子类lq
子类化,并将锁定放在该实现中。之后,我可以确定lq
是线程安全的。
我认为您应该考虑重构以按照您的建议使用ConcurrentQueue<T>
。尽管Q.A.的费用。循环可以确保质量和联锁操作和螺纹纺纱的潜在性能改进。