Main Site Documentation

Pause Timer or ExtendedTimer


#1

Is there any way to pause and resume a Timer/ExtendedTimer in NETMF? I need a way on RWAR to engage and disengage the autopilot…


#2

To resume/pause you can use Timer.Change(int dueTime, int period).

dueTime: Timeout.Infinite = prevent restarting, 0 = restart immediately
period: Timeout.Infinite = disable periodic signaling

It’s not directly a pause/resume, the timer may be fired one time after using the change.
Otherwise dispose the timer and generate a new one on resume.


#3

Yikes, I was hoping for a cleaner solution than that, but, if nothing else…


#4

You could either wrap the timer and implement pause, or do something like below. I kinda favor single thread like this as much easier to reason about for me, then wondering about overlapped events if your changing periods, etc.

public delegate void Action();
public class Timer2 : IDisposable
{
    private ManualResetEvent mre;
    private int isRunning;
    private Action callback;
    private int period;

    public Timer2(Action callback, int period)
    {
        if (callback == null) throw new ArgumentNullException("callback");
        if (period < 0) throw new ArgumentNullException("period");
        this.period = period;
        this.mre = new ManualResetEvent(false); // block until Start().
        this.isRunning = 1; // stopped.
        this.callback = callback;
        new Thread(TimerInternal).Start();
    }

    private void TimerInternal()
    {
        while (isRunning == 1)
        {
            Thread.Sleep(period);
            mre.WaitOne();
            callback();
        }
    }

    /// <summary>
    /// Start timer.
    /// </summary>
    public void Start()
    {
        mre.Set();
    }

    /// <summary>
    /// Pause timer. Call Start to resume.
    /// </summary>
    public void Pause()
    {
        mre.Reset();
    }

    /// <summary>
    /// Stop and close timer.
    /// </summary>
    public void Dispose()
    {
        Interlocked.Exchange(ref isRunning, 0);
        mre.Set(); // allow pass.
    }

    internal static void TestTimer2()
    {
        // Test.  Run a callback every second until count > 10.  Then close timer.
        int count = 0;
        Timer2 t = null;
        t = new Timer2(() =>
        {
            Debug.Print("Timer2 called.");
            if (++count > 10)
            {
                t.Dispose();
                Debug.Print("Timer2 disposed.");
            }
        }, 1000);
            
        t.Start();
    }
}

BTW - I am not entirely sure the Interlocked is required here in MF. Not sure of the memory model or threading model. Does MF simulate threads with continuations on a single thread or more like .Net? Kinda grey area for me currently.


#5

Another way would waste 2 IO’s (maybe only 1).
You could use the USbizi RTC.Setalarm(), connect the pin to another and setup an interrupt on the pin. When the alarm is invoked the interrupt method rises.

Just an idea… :wink:


#6

Hi Chris,

I think using IOs is probably over thinking it, but I might end up using a class like yours to call the autopilot.

Thanks!