最近在对博客园的程序进行性能优化,在优化过程中用到了Dictionary<tkey, tvalue="">,在通过foreach将Dictionary<tkey, tvalue="">中的数据写入数据库时,遇到了这样的错误:
Collection was modified; enumeration operation may not execute. 代码类似这样的: Dictionary<int, int> _dictionary = new Dictionary<int, in>(); //添加数据操作省略 foreach(KeyValuePair<int, int> item in _dictionary) { }
在执行foreach时,其他线程对_dictionary进行了Add操作,改变了_dictionary中的数据,从而产生了上述的异常信息。
那什么会产生这样的异常信息呢?
foreach实际上执行的代码是: Dictionary<int, int>.Enumerator enumerator = _dictionary.GetEnumerator(); try { while (enumerator.MoveNext()) { } } finally { IDisposable d = enumerator as IDisposable; if (d != null) d.Dispose(); }
通过Reflector查看Dictionary<TKey, TValue>.Enumerator.MoveNext()源代码,我们会发现开始处有这样的代码:
if (this.version != this.dictionary.version) { ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion); }
而异常就是在这里发生的,因为Add操作时改变了Dictionary的version,通过查看Insert(TKey key, TValue value, bool add)的源代码会看出。
我觉得Dictionary<TKey, TValue>应该提供一个方法,可以设置在MoveNext时是否进行版本检查,因为有时在foreach操作时,可能并不关心Dictionary中的数据是否被修改,我遇到的就是这样的情况,现在由于这个问题而不能使用foreach,而只能采取其他方法遍历Dictionary<TKey, TValue>中的数据。 我采用的方法是: Dictionary<int, int> _dictionary = new Dictionary<int, in>(); //添加数据操作省略 int[] dataArray = new int[_dictionary.Values.Count]; _ dictionary.Values.CopyTo(evcArray, 0) for (int i = 0; i < dataArray.Length; i++) { }
posted on 2012-07-30 15:16 阅读( ...) 评论( ...)