Exit / cancel methods, while loops by threads: bool, ManualResetEvent or CancellationToken

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).

+6
source share
1 answer

Most often, your threads do not work in hard loops where all your processor loops are, often you expect events of some kind when you wait that you cannot wait on bool. You can have a timeout at your event, wait for a timeout, check the bool, and then return to waiting. This leads to unpleasant code, and also means that your thread will not stop until a timeout occurs, or you do not eat your processor by checking the bool.

The Reset Event is fine, you can work with it, but the CancelellationToken works great and is specifically designed for that.

+2
source

Source: https://habr.com/ru/post/979370/


All Articles