I am writing a program with several threads, each of which contains a while loop, until the user indicates that he should stop. I thought of several ways to get out of loops, and then in threads, and described these approaches below.
Questions
- Are there any pros and cons for everyone?
- Are there any cases when you would use one and not the other?
- I heard several people say they prefer CancellationTokens to exit streams. What attracts this approach compared to the other two?
Following are the approaches.
Bool approach
First, I declared bool and simply stated that the cycles are executed until the user sets bool to false: while(running) { Thread.Sleep(10); /*do work*/ }
while(running) { Thread.Sleep(10); /*do work*/ }
. Then I wondered if this is completely thread safe. What to do if the compiler has done some optimization and moved bool to a register. In this case, the threads will see different values ββfor bool. As a result, I marked bool with the volatile
keyword to avoid compiler optimization.
ManualResetEvent
Approach
My next approach was to create a ManualResetEvent
and just say that bool is working and WaitOne () is false: while(!mre.WaitOne(10)) {/*do work*/}
. This will be locked for 10 ms, and then run the loop again and again until we do mre.Set()
and the loop ends.
Approach CancellationToken
I have not tried this approach yet, but I have read several places that people prefer to cancel threads this way. Apparently this is a thread. You could define a CancellationTokenSource
, call it cts
, and then pass cts.Token
method executed by the new thread, and use the if statement to check whether the cancel was requested: while(!token.IsCancellationRequested) { Thread.Sleep(10); /*do work*/ }
while(!token.IsCancellationRequested) { Thread.Sleep(10); /*do work*/ }
UPDATE 1:
I found a similar entry that concludes that the MRE
approach is much slower than the CancellationToken
approach. For more information, see here: Stopping a stream, ManualResetEvent, volatile boolean, or cancelationToken
UPDATE 2:
When it comes to comparing bool
approach to the other two, Eric Lippert has a good answer here: AutoResetEvent vs. boolean to stop the thread
UPDATE 3:
I found one more important information. CancellationTokens cannot be reset after cancellation. Thus, this is not ideal for when you just want to temporarily abandon the loop in order to start it later. For this, MRE may be better (as you can set and Reset, to your heart content).