Awakening a thread when an event occurs

I would like to receive the following message between two threads:

Thread Alpha does something and then pauses. Then a second stream (beta) and an event that resumes the Alpha stream are added. The cycle continues ...

I did something like below, but I'm not sure if this is the right design. I also noticed that Thread.Suspend() and Thread.Resume() are deprecated. I look forward to hearing any recommendations regarding this implementation, and it is preferable to replace obsolete methods.

 namespace ThreadTester { delegate void ActionHandler(); class Alpha { internal Thread alphaThread; internal void Start() { while (true) { this.alphaThread.Suspend(); Console.WriteLine("Alpha"); } } internal void Resume() { while (this.alphaThread.ThreadState == ThreadState.Suspended) this.alphaThread.Resume(); } } class Beta { internal event ActionHandler OnEvent; internal void Start() { for (int i = 0; i < 15; i++) { OnEvent(); Thread.Sleep(1000); } } } class Program { static void Main(string[] args) { Alpha alpha = new Alpha(); alpha.alphaThread = new Thread(new ThreadStart(alpha.Start)); alpha.alphaThread.Start(); while (!alpha.alphaThread.IsAlive) ; Beta beta = new Beta(); beta.OnEvent += new ActionHandler(alpha.Resume); Thread betaThread = new Thread(new ThreadStart(beta.Start)); betaThread.Start(); } } } 
+6
multithreading c # events
source share
4 answers

Typically, threads are used for parallel processing> one work item. I wonder why your design requires thread A to sleep and thread B to do something, then wake up and continue to work. Why not just run Thread A?

You may find it useful to use .Net 4 Parallel Task Library - Thread A can then initiate an asynchronous task that is automatically executed in a separate thread, and the result is available for Thread A, without the need for explicit cross-flow signaling (which can lead to application freezing if Thread malfunctions A or B).

+1
source share

Here you usually use wait handle , in particular event wait commands.

If you call the WaitOne method on the wait descriptor, it will block your thread until some other thread calls Set in the same wait descriptor.

There are two important simple options for handling events: AutoResetEvent will automatically reset after the stream passes through WaitOne , ManualResetEvent will only reset if you call Reset .

+12
source share

This is a common synchronization problem, and there are several approaches (all of which are pretty easy to mess up if you're not very careful):

  • Wait Handles (Joren already described them).

  • Monitor.Wait and Monitor.Pulse . One of them is that Pulse only wakes up threads that are already on hold, so you need to be careful how you control the locking of the synchronization object.

  • With the new TPL in .NET 4 (also ported back to .NET 3.5), you can configure asynchronous tasks and determine the conditions under which tasks continue based on previously completed tasks. There's a little learning curve to figure out how to structure your code to take advantage of tasks and follow-up, but it's significantly better (ultimately) than the very rocky road that follows the deceptively simple use of low-level synchronization constructs. It also gives you an excellent a way to add more robust error handling and support cancellation of your logic, as details of their coordination are baked in TPL.

+10
source share

Your code has a β€œfeeling” of the producer-consumer model, but is not implemented correctly. You definitely don't want to use Thread.Resume and Thread.Resume in this way (or in any way actually). It’s actually easy to get the sequence and signaling as you want by implementing the canonical producer-consumer pattern through the BlockingCollection class.

 public class ProducerConsumer { private BlockingCollection<object> m_Queue = new BlockingCollection<object>(); public ProducerConsumer() { new Thread(Producer).Start(); new Thread(Consumer).Start(); } private void Consumer() { while (true) { object item = m_Queue.Take(); // blocks when the queue is empty Console.WriteLine("Consumer"); } } private void Producer() { while (true) { m_Queue.Add(new object()); Thread.Sleep(1000); } } } 

In the above code, Consumer and Producer will be equivalent to your alphaThread and betaThread respectively.

+7
source share

All Articles