Possible race status using ManualResetEvent

Problem:

I am trying to drop 6 threads from ThreadPool to work on individual tasks. Each ManualResetEvent task is stored in an array of manual reset events. The number of threads corresponds to the index in the ManualResetEvent array.

Now it happens that after I initiated these 6 threads, I quit and wait for the threads to finish. A thread is waiting on the main thread.

Now several times it happens that my waiting logic does not return even after a long time (2 days that I saw). Here is sample code for thread wait logic

foreach (ManualResetEvent whandle in eventList) { try { whandle.WaitOne(); } catch (Exception) { } } 

According to the .WaitOne documentation. This is a synchronization call that causes the stream to not return if the Set event is not received from the stream.

Sometimes my threads have less work, and they may even come back before I get to the waiting logic. Is it possible that .WaitOne () will wait for the Set () event, even if it was received in the past? Is the correct logic to wait for all threads to complete?

+4
source share
2 answers

(Note: I think your best bet is Parallel.Invoke() - see below in this answer.)

What you do will work fine, so the problem may be due to the fact that for some reason one of your threads is blocked.

You should be able to debug this message quite easily - you can attach a debugger and break into the program, and then look at the call stack to find out which threads are blocked. Get ready to scratch your head if you discover a race condition though!

Another thing to know about is that you cannot do the following:

 myEvent.Set(); myEvent.Reset(); 

nothing (or very little) between .Set() and .Reset() . If you do this when multiple threads are waiting on myEvent , some of them will skip the set event! (This effect is poorly documented on MSDN.)

By the way, you should not ignore exceptions - always register them in some way, at least.


(This section does not answer the question, but may provide some useful information)

I also want to mention an alternative way to wait for threads. Since you have a set of ManualResetEvents, you can copy them into a simple array and pass it to WaitHandle.WaitAll() .

Your code might look something like this:

 WaitHandle.WaitAll(eventList.ToArray()); 

Another approach to waiting for all threads to complete is to use a CountdownEvent . It becomes signaled when the countdown reaches zero; you start counting the number of threads, and each thread signals this when it exits. Here is an example here .

Parallel.Invoke()

If your threads do not return values, and all you want to do is start them and then start the start thread to exit them, then I think Parallel.Invoke() would be the best way for everyone. This avoids the need to synchronize yourself.

(Otherwise, as svick says in the comments above, use Task , not the old thread classes.)

+3
source

I do not answer this question directly. Here is what you should do:

Run the tasks using Task.Factory.StartNew and use Task.WaitAll(Task[]) to wait for them. You do not need to deal with such events. Exceptions will apply well to the forking thread. You no longer need the old ThreadPool API.

Hope this helps.

+3
source

All Articles