Looking through the code, much as Hodgman suggests, there are a number of unprotected items taking place and you need to get your protections cleaned up. But, additionally, I would suggest removing the use of the Event type. Event in Windows should be avoided as it doesn't tend to work well for most things people use it for. Generally speaking, I would replace that with a semaphore. I suggest this because event doesn't work as most folks expect and it is a very common cause of deadlocks and missed work. The problem is that events are simply toggles set true or false, if you call set event multiple times, the event is still only set or unset to workers, hence only one thread gets the event and then resets it, even though there are more work items that should be issued to other threads. NOTE: the behavior can be different based on how you construct the event, if it is not auto reset, multiple threads could attempt to pull work when there is only one item queued.
I don't claim this is your problem, but in conjunction with Hodgmans suggestion, it would be a start to likely fixing this code.