Q: Is this the right paradigm for a preemptive, exclusive function in a multithreading environment? I am implementing a preemptive, exclusive function in a multithreaded  environment, where if a cancel request occurs even when the function is not running, when the function does run, it knows about this cancel request and does not run. I came across various different ways to do this in C# using ManualResetEvent and the like(something like the answer to this question Synchronizing a Timers.Timer elapsed method when stopping), however I was wondering if something as simple as what I am doing in the code below would suffice. Are there any inadvertent bugs that I am introducing here?
bool cancel = false;
bool running = false;
object Lock = new object();
void PremptiveExclusiveFunction() {
  lock(Lock) {
    if(running)
      return;
    running = true;
  }

  for(int i=0; i < numIter; i++) {
    lock(Lock) {
      if(cancel) {
       cancel = false;
       running = false;
       return;
      }
    }

    // iteration code
  }

  lock(Lock) {
   running = false;
  } 
}

void Stop() {
  lock(Lock) {
    cancel = true;
  }
}

As far as I know, this seems to handle my 3 requirements: 
1. ability to preempt 
2. exclusivity in time, where this only copy of this function can be running 
3. a cancel request not being lost because Stop is called before PreemptiveExclusiveFunction 
I'd be grateful if more experienced minds could point out if I am indeed missing something.

A: Entire function body can be locked to eliminate the running boolean:
object @lock = new object();

volatile bool cancel = false;

void Function () {
    if (!Monitor.TryEnter(@lock))
        return;
    try {

        for (var i = 0; i < 100; i++) {
            if (cancel) {
                cancel = false;
                return;
            }

            // code
        }

    } finally {
        Monitor.Exit(@lock);
    }
}

void Stop () {
    cancel = true;
}

+ Notice the volatile keyword:
http://msdn.microsoft.com/en-us/library/vstudio/x13ttww7(v=vs.100).aspx
