c# - Exception when attempting to modify Dictionary -


i creating dictionary manage threads , ran exception when attempt clear dead threads after adding threads dictionary.

using system; using system.collections.generic; using system.threading;  namespace syscat {     public class threadmanager {         public static readonly threadmanager globalthreadmanager = new threadmanager( );          /// <summary>         /// initializes new instance of <see cref="syscat.threadmanager"/> class.         /// </summary>         public threadmanager( ) {          }          /// <summary>         /// create new threadmanager threads within basetm , deinitializes basetm         /// </summary>         public threadmanager( threadmanager basetm ) {             this.threads = basetm.threads;             basetm.threads.clear( );         }          private dictionary<guid,thread> threads = new dictionary<guid, thread>( );          /// <summary>         /// attempts obtain unused threadid within attempt limit         /// </summary>         /// <returns>the unused threadid, if found</returns>         /// <param name="attempts">the number of iterations try.</param>         public guid getunusedthreadid( int attempts ) {             lock( threads ) {                 guid threadid;                 int totalattempts = attempts;                 while( threads.containskey( ( threadid = guid.newguid( ) ) ) ) {                     attempts--;                     if( attempts == 0 )                         throw new noopenthreadidexception( totalattempts );                 }                 return threadid;             }         }          /// <summary>         /// attempts thread via threadid, if exists         /// </summary>         /// <returns>the thread</returns>         /// <param name="threadid">the threadid use</param>         public thread getthread( guid threadid ) {             lock( threads ) {                 thread tryget;                 if( !threads.trygetvalue( threadid, out tryget ) )                     throw new argumentexception( "specified threadid not exist in threadmanager" );                 return tryget;             }         }          /// <summary>         /// attempts threadid via thread         /// </summary>         /// <returns>the threadid</returns>         /// <param name="thread">the thread use</param>         public guid getthreadid( thread thread ) {             lock( threads ) {                 if( threads.containsvalue( thread ) ) {                     foreach( guid id in threads.keys ) {                         thread t;                         threads.trygetvalue( id, out t );                         if( t.equals( thread ) )                             return id;                     }                     // should never here                     return guid.empty;                 }                 else                     throw new argumentexception( "specified thread not exist in threadmanager" );             }         }          /// <summary>         /// adds thread, unless cannot find open threadid         /// </summary>         /// <returns>the threadid used register thread</returns>         /// <param name="thread">the thread register</param>         public guid addthread( thread thread ) {             lock( threads ) {                 guid id;                 try {                     id = getunusedthreadid( 500 );                 }                 catch( noopenthreadidexception e ) {                     throw e;                 }                 threads.add( id, thread );                 return id;             }         }          /// <summary>         /// attempts clear stopped , null threads         /// </summary>         /// <returns>the number of dead threads cleared</returns>         public int cleardeadthreads() {             int cleared = 0;             lock(threads) {                 foreach( guid id in threads.keys ) {                     thread thread;                     threads.trygetvalue( id, out thread );                     if( thread == null ) {                         // not exist, thread dead                         cleared++;                         threads.remove( id );                         continue;                     }                     if( !thread.isalive ) {                         // not alive, thread dead                         cleared++;                         threads.remove( id );                         continue;                     }                 }             }              return cleared;         }          public class noopenthreadidexception : exception {             public noopenthreadidexception( int attempts )                 : base( string.format( "unable find open threadid within attempt limit of {0}", attempts ) ) {             }         }     } } 

and getting exception: system.invalidoperationexception message: collection modified; enumeration operation may not execute

i unsure why happening, appreciated.

this code used test it:

using system; using system.collections; using system.io; using system.collections.generic; using system.threading;  using _tm = syscat.threadmanager;  namespace syscat {     public class syscat {         thread t = new thread( new threadstart( delegate {             while(true) thread.sleep(250);         } ) );         thread t2 = new thread( new threadstart( delegate {          } ) );         thread t3 = new thread( new threadstart( delegate {          } ) );         _tm.globalthreadmanager.addthread( t );         _tm.globalthreadmanager.addthread( t2 );         _tm.globalthreadmanager.addthread( t3 );             console.writeline( _tm.globalthreadmanager.cleardeadthreads( ) );             console.readline( );         }     } } 

you can not modify ienumerable while enumerating on it.

you can simple hack , copy of enumerating changes in not result in system.invalidoperationexception.

for example instead of

foreach( guid id in threads.keys)  

use

foreach( guid id in threads.keys.tolist())  

keep in mind can use data structures supports concurrency


Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -