本文介绍了InvalidOperationException:集合已修改-尽管锁定了集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个同步的哈希表,我会定期从中删除一些条目。多个线程运行此代码。所以我锁定了整个foreach,但有时仍然会收到InvalidOperationException:在Hashtable.HashtableEnumerator.MoveNext()处修改了collection-即在foreach循环中。
我在做什么错?

I have a synchronized hashtable, from which I regularly remove some entries. Multiple threads run this code. So I lock the entire foreach, but I still sometimes get InvalidOperationException: Collection was modified ... at Hashtable.HashtableEnumerator.MoveNext() - i.e. in the foreach loop.What am I doing wrong? Isn't locking enough?

private static readonly Hashtable sessionsTimeoutData = Hashtable.Synchronized(new Hashtable(5000));

私有静态无效ClearTimedoutSessions()
{
List keysToRemove = new List();现在,
长= DateTime.Now.Ticks;
锁定(sessionsTimeoutData)
{
TimeoutData timeoutData;
foreach(sessionTimeoutData中的DictionaryEntry条目)
{
timeoutData =(TimeoutData)entry.Value;
if(现在-timeoutData.LastAccessTime> timeoutData.UserTimeoutTicks)
keysToRemove.Add((ulong)entry.Key);
}
}
foreach(keyToToMove中的长键)
sessionsTimeoutData.Remove(key);
}

private static void ClearTimedoutSessions(){ List keysToRemove = new List(); long now = DateTime.Now.Ticks; lock (sessionsTimeoutData) { TimeoutData timeoutData; foreach (DictionaryEntry entry in sessionsTimeoutData) { timeoutData = (TimeoutData)entry.Value; if (now - timeoutData.LastAccessTime > timeoutData.UserTimeoutTicks) keysToRemove.Add((ulong)entry.Key); } } foreach (ulong key in keysToRemove) sessionsTimeoutData.Remove(key);}

推荐答案

您要使用 SyncRoot 是同步的 Hashtable 的方法将锁定的对象:

You want to lock using SyncRoot which is the object that the methods for a synchronized Hashtable will lock on:

lock (sessionsTimeoutData.SyncRoot)
{
    // ...
}

请参见:

通过集合进行枚举本质上不是线程安全的
过程。即使集合同步
,其他线程仍可以
修改该集合,这会导致
枚举器抛出异常。
为了保证
枚举期间的线程安全,您可以在整个
枚举期间锁定
集合,也可以捕获其他$ b $所做的更改导致的异常

以下代码示例显示
如何在整个
枚举期间使用
SyncRoot锁定集合:

The following code example shows how to lock the collection using the SyncRoot during the entire enumeration:

Hashtable myCollection = new Hashtable();
lock(myCollection.SyncRoot)
{
    foreach (object item in myCollection)
    {
        // Insert your code here.
    }
}


这篇关于InvalidOperationException:集合已修改-尽管锁定了集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-26 09:35