6

I need some way to do the following efficiently in C#:

Make program execution stop until certain value is changed.

Note: I do not want to make it with a while loop to avoid wasting cpu power..

Edit: And I want it to respond as quickly as possible after value has changed..

Edit: This will be inside my class method that is called by another code, however the value to be checked is inside my class... The method is supposed to wait until others code evaluate and change my value.. then it must continue to do its work.. unfortunately this is done many times(so I need to care for performance)

Betamoo
  • 14,964
  • 25
  • 75
  • 109
  • Is this application a Windows service? You don't specify, and it doesn't really make sense to literally pause execution in an interactive (event-driven) application. – Aaronaught May 21 '10 at 19:38
  • 5
    Your requirements are contradictory. You reject busy waiting because of its power consumption, and you require it to be **as responsive as possible**, but busy waiting is what is going to be **as responsive as possible**. What would be better is if you told us about your *budget*. "As fast as possible" tells us nothing; "within one millisecond" tells us rather a lot. A solution which is responsive to within a millisecond might be rather different than a solution responsive to a microsecond, or to a second. – Eric Lippert May 21 '10 at 19:45
  • 1
    what exactly do you mean by make execution stop? is it some constantly running thread that you have to interrupt at a certain point? how do you intend to make it stop? or is it more like a short event that you'd like to occur on a value change? – Mark Synowiec May 21 '10 at 20:13

4 Answers4

15

Monitor.Wait and Monitor.Pulse

treehouse
  • 2,521
  • 1
  • 21
  • 39
  • There is no `Monitor.Set`. Did you mean `Monitor.Pulse` or `Monitor.PulseAll`? – Aaronaught May 21 '10 at 19:36
  • If you want to sleep completely without any spinning, this is the way to go. However this requires that the code that sets the value knows how to pulse on the correct object, or your code will never wake up. – Stephan May 21 '10 at 19:39
  • 1
    @Stephen, so use a property, and pulse when the set method is called – Martin May 21 '10 at 20:04
7

If the value you're waiting for is set somewhere else in the same application you can use a wait handle:

AutoResetEvent waitHandle = new AutoResetEvent();
...
//thread will sleep here until waitHandle.Set is called
waitHandle.WaitOne();
...
//this is where the value is set
someVar = someValue;
waitHandle.Set();

(note that the WaitOne and Set have to occur on separate threads as WaitOne will block the thread it is called on)

If you don't have access to the code that changes the value, the best way to do it is, as others have said, use a loop to check if the value has changed and use Thread.Sleep() so you're not using as much processor time:

while(!valueIsSet)
{
    Thread.Sleep(100);
}
Phil Lamb
  • 1,407
  • 10
  • 15
  • /agree... this is the best possible way – csauve May 21 '10 at 19:42
  • If the goal is to BLOCK a thread, this is the best way. To block the main thread and prevent any new inputs until the event occured, then place the .WaitOne() in the main thread. In another thread, where the value that triggers the wakeup, place the .Set(); – Roast May 21 '10 at 20:02
6
while(some-condition-here)
{
    Thread.CurrentThread.Sleep(100); // Release CPU for 100ms
}

It's called spin-sleeping I think. Of course you can adjust the 100 to whatever you feel is fit. It's basically the timeout for each check.

There's other ways of doing it, but this is the easiest and it's quite efficient.

It's actually referenced in this e-book:

Threading in C# by Joseph Albahari: Part 2: Basic Synchronization

Aren
  • 54,668
  • 9
  • 68
  • 101
  • I've used this before, but I'm not a fan of it. (so I'll neither mod your answer up or down.) It always "smelled" wrong to me. – Pretzel May 21 '10 at 20:24
  • @Pretzel I've referenced a book (e-book) that talks about it. – Aren May 21 '10 at 20:34
  • Just because its in a book doesn't make it right. Also, to quote the author, "Perhaps its biggest use is when a programmer has given up on getting a more complex signaling construct to work!" – Matt Jordan May 21 '10 at 20:39
  • @Aren B: Hey, I'm not knocking it. I use it on occasion, but I always feel like my code just got a little "dirty" by using it. Like Matt Jordan, I will also quote the article: "The larger [the sleep time delay], the more CPU-efficient this is; the trade-off being in increased latency. Anything above 20ms incurs a negligible overhead" -- as long as you're okay with such a latency, then I guess you're fine. – Pretzel May 21 '10 at 21:13
  • I guess my only other suggestion would be if you are using such a spin-sleep technique in the primary GUI thread would be to add: Application.DoEvent() so that the GUI stays responsive to Events (aka. the user) while waiting for the condition to be satisfied -- Assuming that you have a GUI, that is... – Pretzel May 21 '10 at 21:16
  • Again, this never "smelled" right to me, but I've used it on occasion. :-) – Pretzel May 21 '10 at 21:25
3

You can use the Observer design pattern. It is designed to solve problems like yours.

This pattern mainly contains a subject and an observer. You can have it to respond to any change and very quickly.

You can find more information and sample code here

pavanred
  • 12,717
  • 14
  • 53
  • 59
  • If the architecture allows it (i.e. you have control over what you're monitoring), this can be a good solution. You get a very fast response because you receive the event right after the change has happened. The main caveat is that you're executing in the context of the thread that performed the change, which can sometimes be problematic. – Dan Bryant May 21 '10 at 19:50