One of the projects I work on is a windows service that listens to the Tibco bus and handles messages. Since it always runs we decided to use it for another purpose – periodic calls. Calls that need to be done every few seconds/minutes.
One of those calls is for handling traffic load reports and another for handling some messages in bulk (we receive thousands of those messages every minute and required to handle them every 15 seconds). The traffic load synching is added on startup but the bulk handler is added later.
For that purpose I created a nice little class called PeriodicCaller that has a List of PeriodicCall (Action, when was last called, TimeSpan between calls). PeriodicCaller starts a new thread that calls the list using foreach.
The problem we faced though was that sometimes the Add operation failed, and we were unlucky enough to receive this exception:
System.InvalidOperationException was unhandled
Message=Collection was modified; enumeration operation may not execute.
Source=mscorlib
StackTrace:
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at ListAddAndForEach.PeriodicCaller.Caller()
Why is luck a factor? Because this only happens when the Add is called in the middle of the foreach loop.
The fix is quite easy instead of using a foreach loop use a for loop (and just ignore Resharper’s warning:
because sometimes they are just wrong…).