ManualResetEvent vs while loop

1.5k views Asked by At

ManualResetEvent basically says to other threads "you can only proceed when you receive a signal to continue" and is used to pause execution for certain threads until certain condition has been fulfilled. What I want to ask is that why ManualResetEvent when we could easily achieve what we want by using a while loop? Consider the following context:

public class BackgroundService {

ManualResetEvent mre;
public BackgroundService() {
    mre = new ManualResetEvent(false);
}
public void Initialize() {
    // Initialization
    mre.Set();
}

public void Start() {
    mre.WaitOne();
    // The rest of execution
}
}

is somewhat similar to

public class BackgroundService {

bool hasInitialized;
public BackgroundService() {

}
public void Initialize() {
    // Initialization
    hasInitialized = true;
}

public void Start() {
    while (!hasInitialized)
    Thread.Sleep(100);
    // The rest of execution
}
}

Is there any particular context where ManualResetEvent is more suitable than a while loop?

2

There are 2 answers

0
Jon Skeet On BEST ANSWER

Is there any particular context where ManualResetEvent is more suitable than a while loop?

Absolutely. There are two primary reasons: latency and efficiency.

Context-switching the thread to start it running again is relatively expensive, when it's just going to go back to sleep, and the approach you've given will take an average of 50ms to respond to the hasInitialized variable being set - assuming it responds at all. (You don't have any explicit memory barriers, so it's possible that the thread won't actually see a change to the variable at all. I suspect that calling Thread.Sleep effectively adds a memory barrier, but it's not guaranteed.) With OS/CLR-level synchronization primitives, a thread can respond much faster.

0
markmnl On

Using signals such as that provided ManualResetEvent is more efficient. Using a while loop as you have means after roughly every 100 milliseconds, i.e. 10 times a second, other threads have to stop running so your thread to check the condition has to run, this context switch when the condition is mostly false is less efficient.

However something smells very fishy in your code, why would you have such code polling when something is initialized? If the initialisation is asynchronous there will already be some notification mechanism, e.g. a callback, when it is done so the polling is unnecessary.