views:

234

answers:

4

I have several lines of a method that I would like to ensure that there is no context switch to another thread while executing these? Yes, re-architecting is an option but it would be far more expedient for now if I could do this.

Is this possible? If not then does anyone know the reasoning behind the decision?

Edit: The reason I am asking is that I have a class responsible for returning a value, the value is provided via an event so when GetValue() is called, the thread needs to block until the event is raised. So we have:

public class ValueResolver {
  IPersistentNotifier _notifier;
  IValueMonitor _monitor;
  Value _value;
  ManualResetEvent _resolvedEvent = new ManualResetEvent(false);
  public ValueResolver(IPersistentNotifier notifier, IValueMonitor monitor) {
    _notifier = notifier;
    _monitor = monitor;
    _monitor.ValueAcquired += ValueAcquired;
  }
  public Value GetValue() {
    _value = null;
    persistentNotifier.Show("Getting Value")
    _monitor.Start();
    _resolvedEvent.WaitOne(60000, false);
    return _value
  }
  public void ValueAcquired(Value val) {
    _value = val;
    _monitor.Stop();
    _notifier.Hide();
    _resolvedEvent.Set();
  }
}

Only way I can think of writing a test for this is something like (in rhino mocks)

var monitor = MockRepository.GetMock<IValueMonitor>() 
monitor.Expect(x=>x.Start()).Do(new Action(() => {
  Thread.Sleep(100);
  monitor.Raise(y=>y.ValueAcquired, GetTestValue());
});

but any suggestions are welcomed.

+9  A: 

No, you can't. You can use a lock to make sure that no other threads will enter sensitive pieces of code to do with your operation, but that's all.

As for the "why" - it's generally not needed, and would be slightly strange in a pre-emptive operating system on a relatively high-level platform. It may be possible in driver code, but it's not usually needed in user code.

Note that "other threads running" doesn't necessarily mean a context switch anyway, given multi-core and multi-processor machines.

EDIT: Despite your edit, I still don't see why it's a problem for there to be a context switch. If the thread has to block anyway, it's pretty much bound to context switch to a different thread. I agree it's a slightly annoyance that you have to wait for (say) 100ms or so to be confident that your test will have let everything happen on the other thread that you need, but you definitely don't need to ensure that it won't context-switch.

Jon Skeet
I'm worried about the event being raised between the _monitor.Start() and the WaitAndSet instruction executing
George Mauer
Well, that sounds like you need a lock to make sure that doesn't happen. Could you use the normal Monitor class and Monitor.Pulse/Wait instead? That makes it easier to avoid that sort of thing.
Jon Skeet
+3  A: 

Context switch is the method by which OS tries to be "fair" to the all threads\processes executing in the system. Based on the OS, for instance Windows, implements the priority based preemptive scheduling. Preemptive scheduling means if the higher priority thread is ready for execution then current thread has to leave the CPU.

Writing an atomic code means interrupting the OS scheduling, which OS doesn't allow. Also, Scheduling in Windows event driven. You cannot hold the CPU unless there are no waiting threads of same\higher priority.

aJ
Hmm, that's kind of what I thought, might make my unit tests slightly more brittle though...
George Mauer
Why would your unit tests rely on the thread not context-switching?
Jon Skeet
see edit for why I am doing this
George Mauer
+2  A: 

Windows, and every other modern OS, is a preemptively scheduled multiprocessing OS. The OS is in charge of allocating timeslices to individual processes, and individual processes can not hog the system.

Imagine if your code entered an infinite loop inside your magic "no context switches" code section. The entire system would freeze and have to be rebooted.

jalf
A: 

Why sit around for the event to fire? Can't you can write in a method on (IValueMonitor) to "get" your value?

Perhaps I don't understand...

Ben
Sure, in my case, the IValueMonitor checks a service periodically to see if the value returned by that service exceeds a certain threshold.Think of an application that takes the weight of an object on a scale. In the appropriate point in the application it pauses with a "place object on scale" message then monitors the scale's weight provider to see if the weight threshold is exceeded by the current value. Only then does it continue (or on timeout or abort).
George Mauer