-1

I have worker threads and a master thread, the master thread is linked to the UI and can ask the workers to stop working.
My threads run an "infinite" loop that checks a boolean, which value can be modified by the master to stop all threads.

In my worker threads:

while (not_terminated)
{
    /* Process */
}  

The master thread :

private void stop_btn_clicked(object sender, RoutedEventArgs e)
{
    not_terminated = false;
}

I need my master thread to pause the worker thread, I thought about a read-only mutex that all workers can read but writable only by the master, something like a "shared_mutex" from C++. My current solution is to use Thead.Suspend() and Thread.Resume() but they appear to be a very bad practice...
I'm new to C# and I found System.Threading.Mutex but the WaitOne() function blocks if no signal is sent to the mutex, and in fact I'm looking for the opposite : block if a signal is sent.

How would you do it?

EDIT: I'd like to avoid external libraries

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Maskim
  • 382
  • 2
  • 4
  • 18
  • 2
    Maybe use a [`ManualResetEvent`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.manualresetevent?view=net-5.0) ? – Matthew Watson Dec 07 '20 at 09:51
  • Related: [Pause/resume a thread in C#](https://stackoverflow.com/questions/61499676/pause-resume-a-thread-in-c-sharp) – Theodor Zoulias Dec 07 '20 at 10:03
  • Thanks Matthew, I'm looking at the doc to implement it. @TheodorZoulias, I'd like to avoid external libraries, and as you suggested in the linked post, `Suspend()` and `Resume()` are not only deprecated but also dangerous (can pause thread in critical section) – Maskim Dec 07 '20 at 10:16
  • In case the `PauseToken` is exactly what you want, then you could just grab the [source code](https://github.com/StephenCleary/AsyncEx/blob/master/src/Nito.AsyncEx.Coordination/PauseToken.cs) and embed it in your project. There is no requirement for adding a third-party dependency if you don't want to. Or you could grab it from [here](https://devblogs.microsoft.com/pfxteam/cooperatively-pausing-async-methods/ "Cooperatively pausing async methods"). – Theodor Zoulias Dec 07 '20 at 10:23
  • Can you please let us know what you're trying to do with the threads? Maybe we can suggest a better way than pausing, etc. – Enigmativity Dec 07 '20 at 22:01
  • @Enigmativity I'm making a simulator with a GUI in WPF to simulate 256 worker robots from my company : each robot is represented by a dedicaded thread. In the GUI, we can start the simulation and pause it. – Maskim Dec 08 '20 at 07:21
  • 1
    @Maskim - That's terribly inefficient. Each thread takes at least a Megabyte. Yo're using 256 MB just for threads. You also typically have only have 8 cores - so 248 threads are idle. What is each thread doing? – Enigmativity Dec 08 '20 at 07:29

1 Answers1

1

just checking a boolean would not be safe, you will need a memory barrier to ensure thread safety. I believe specifying the bool as volatile should do that.

It sounds like you want to send a signal between events, so one of manualResetEvent/manualReseteventSlim/autoResetEvent might be appropriate. You also have the Monitor that is used by locks and similar to a Mutex, but that might not be appropriate for signaling.

If you only need to stop the threads once, a cancellationToken/cancellationTokenSource might be appropriate.

The modern way is to not use dedicated threads, and instead use threads from the threadpool when and if they are needed. This also fits into the async/await and task pattern. If you need a thread to have exclusive access to a resource you can use a task scheduler. For example ConcurrentExclusiveSchedulerPair or LimitedConcurrencyLevelTaskScheduler

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • Thank you, [as suggested by Matthew Watson](https://stackoverflow.com/questions/65179293/thread-sync-pause-worker-threads?noredirect=1#comment115229907_65179293) and you, I used ManualResetEventSlim and it works like a charm. My "foreach" over all my threads to `Suspend()` them was VERY slow (~10sec) ... – Maskim Dec 07 '20 at 11:03