I am not sure I fully understood what how the GPIO port behaves in your example, but assuming it can generate interrupts as the board's button does, I would use a Timer instead of a while loop and write something like the following example.
N.B. I did not get the occasion to compile/test the following code, adapted from something I did here. It's thus just the general idea of what I would do.
public class Process
const int STARTUP_TIME = 5000;
const int PERIOD = 1000; //We assume that ReadSensorValuesAndDoStuff() execution takes less than 1 second
bool isEnabled = true;
InterruptPort button = new InterruptPort(Pins.ONBOARD_SW1, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeBoth);
button.OnInterrupt += new NativeEventHandler(button_OnInterrupt);
TimerCallback workTimerCallBack = DoWork;
Timer workTimer = new Timer(workTimerCallBack, null, STARTUP_TIME, PERIOD);
private void DoWork(object state)
void button_OnInterrupt(uint data1, uint data2, DateTime time)
isEnabled = !isEnabled;
Every second, DoWork() will be called and, if isActive is true (which is the default value), ReadSensorValuesAndDoStuff() will be called.
When the board's button is pushed, the _OnInterrupt handler will be called and the isActive will be inverted, going from true to false, stopping the calls to ReadSensor...(). When the button will be released or pushed again (depending on the chosen Port.InterruptMode), the isActive variable will be returned to true, and ReadSensorValuesAndDoStuff() will be called again.
Note that with .NET, a Timer has an "enabled" property that I would use instead of the isEnabled variable.
Hope it helps,
P.S. While verifying my posted answer, I noticed the "without a Timer" in the title of your post