this.eventCollection.Remove(key);的时候报错:
线程出错了System.InvalidOperationException: 集合已修改;枚举操作可能不会执行。程序是个老程序,很多东西没办法改.现在只知道 集合对象是N个线程在共同操作.但之前Remove操作是被注释掉的.我把他启用之后这个老程序就开始报错了.我想确认一个问题:我 lock(this.eventCollection)
{
this.eventCollection.Remove(key);
}之后,是否能达到真正锁住对象排除BUG的效果.
因为我的记忆里好像这样就能控制住这个对象,知道移除操作完成才释放.这样就避免了正在移除的时候 其他线程ADD而导致的BUG.求回答:是/否 
如果否的话 求解释.

解决方案 »

  1.   

    感覺是否用到像foreach這樣的枚举操作,如果有這個的話,操作當中是不允許對集合進行修改的。
      

  2.   

    肯定有foreach.我帖子问的有问题,不应该是ADD与 REMOVE冲突,而是REMOVE与foreach冲突.
    现在我想知道:
    REMOVE如果lock了,那么这个时候同时发生的foreach是否会被强行暂停?
      

  3.   

    否。lock(this.eventCollection)相当于你在卫生间挂牌有人,本身不能阻止别人闯入。
    所以需要在其他用到卫生间的地方(比如其他线程ADD),也要尊重规则,也要排队挂牌。
      

  4.   


    那你不要在foreach中Remove不就可以了?
      

  5.   


    如果foreach之前申请了lock,那么不会有同步问题。因为Remove也要拿到lock,两个动作不会同时发生。
      

  6.   

    之后,是否能达到真正锁住对象排除BUG的效果. 
    //理论上讲,如果共享资源被其中一个线程lock,其他试图访问该共享资源的线程将被阻止。直到该资源被解锁。
    还有一种方法,我在多线程写日志时用到的:      Mutex mu = new Mutex(false);//互斥元,保证些日志的时候,日志文件共享读写不出错
          protected void SetMSG(string msg)
          {
                mu.WaitOne();
                NomalFunction.WriteNomalLog(msg);
                mu.ReleaseMutex();       }
      

  7.   

    谢谢各位.还有一点就是比较奇怪:之前虽然没有  remove操作. 但是也会有 update 和 add 啊 为什么老代码就没有这个BUG呢?(remove线程在老代码里是被注释掉的,所以可能当时这个写法就有问题)难道update 和 add 是不会有相互影响的?这个集合是这样new 的:eventCollection = Hashtable.Synchronized(new Hashtable());添加方法:this.eventCollection.Add(name,elapseObj);更新方法:
    EventElapseObj elapseObj = (EventElapseObj)eventCollection[key];
    elapseObj.ChangeAddTime();按这样看的话.
    ADD与eventCollection[key]的内部元素修改(不移除只修改)是不会产生BUG的.
    也就是说Hashtable的ADD与UPDATE是异步兼容的?