当我的多线程应用程序修改同一个对象并且 List 对象无法处理同时向列表添加对象的两个线程时,我经历了惨痛的教训。
我做了一些研究,发现我可以使用锁来避免这种情况发生,在应用程序顺利运行一个月后,即使锁定对象就位,它也会再次发生。我不明白怎么还会发生这种情况。 错误消息与之前相同: 1-源数组不够长。检查 srcIndex 和长度,以及数组的下限。 2-索引超出了数组的范围。
在类私有(private)成员中我有这个成员变量
private static readonly object _syncLock = new object();
在公共(public)职能
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 和长度,以及数组的下限:
在System.Array.Copy(数组sourceArray,Int32 sourceIndex,数组destinationArray,Int32 destinationIndex,Int32长度, bool 可靠)在System.Collections.Generic.List1.Insert(Int32索引,T项)在JE.ThunderHead C:\TFS\LMS\Release\LM_05\LM_05.01\Solutions\ThunderHead\JE.Thunderhead.Business\中的.Business.AttachFragments.GetXMLFragment(字典
2queuedLetters、GroupNode GroupNode、GroupNode ParentGroupNode、StoredProcedure storageProcedure) AttachFragments.cs:位于 C:\TFS\LMS\Release\LM_05\LM_05.01\Solutions\ThunderHead\JE.Thunderhead.Business\AttachFragments.cs 中 JE.ThunderHead.Business.AttachFragments.UpdateFragments(Object stateinfo) 的第 135 行:第99行
2- 索引超出了数组范围:
在 System.Collections.Generic.List1.Add(T item) 在 JE.ThunderHead.Business.AttachFragments.GetXMLFragment(Dictionary
2 queuedLetters, GroupNode GroupNode, GroupNode ParentGroupNode, StoredProcedure storeProcedure) 在 C:\TFS\LMS\Release\LM_05\LM_05.01\Solutions\ThunderHead\JE.Thunderhead.Business\AttachFragments.cs:第 231 行
最佳答案
从您发布的堆栈跟踪来看,该列表上似乎有一个 Insert
,但您未在此处显示。如果是这种情况,您需要使用相同的锁定对象来锁定该 Insert
。
关于c# - 多线程Web服务访问和修改List对象不是线程安全的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7193047/