Oliver Apel
Oliver Apel

Reputation: 1858

How to set up a application-wide Timer?

I want to have a timer in my windows phone 8 app, that´s counting/running independent of current shown page. It should connect to server - when possible in a UI independet task/thread - and store data in a global object/list.

The Independence from current shown page is my point.

I tried following in App.xaml.cs:

public partial class App : Application
{
    // creating timer instance
    DispatcherTimer gAppTimer = new DispatcherTimer();
    // timer interval specified as 1 minute
    gAppTimer.Interval = TimeSpan.FromSeconds(60);
    // Sub-routine OnTimerTick that will be called at specified intervall
    gAppTimer.Tick += OnTimerTick;
    // starting the timer
    gAppTimer.Start();
    public void OnTimerTick(Object sender, EventArgs args)
    {
        // text box property is set to current system date.
        // ToString() converts the datetime value into text
        MessageBox.Show("TIMER fired");
    }
    :
    :

But this doesn´t work. Than I tried just declaring the object in App.xaml.cs:

public partial class App : Application
{
    // creating timer instance
    DispatcherTimer gAppTimer = new DispatcherTimer();
    public void OnTimerTick(Object sender, EventArgs args)
    {
        // text box property is set to current system date.
        // ToString() converts the datetime value into text
        MessageBox.Show("TIMER fired");
    }
    :
    :

And on my startpage.xaml.cs:

    // timer interval specified as 1 minute
    App.gAppTimer.Interval = TimeSpan.FromSeconds(60);
    // Sub-routine OnTimerTick that will be called at specified intervall
    App.gAppTimer.Tick += OnTimerTick;
    // starting the timer
    App.gAppTimer.Start();

But this doesn´t work, too.

Any ideas how to handle my Problem? What I don´t want to use is a Background Task, because it runs only every 30 minutes. My solution should only run, if the app is "active" (in foreground).

Upvotes: 0

Views: 1280

Answers (2)

yasen
yasen

Reputation: 3580

That's normally done using a static or singleton class. Both will be global and you'll have access to them from every page.

Also, the DispatcherTimer invokes it's TimerTick method on the UI thread. If you don't need to be in the UI thread, you should use a System.Threading.Timer, which invokes a method in a background thread.

Here's an example:

public static class SomeManager {
    private static Timer gAppTimer;
    private static object lockObject = new object();

    public static void StartTimer() {
        if (gAppTimer == null) {
            lock (lockObject) {
                if (gAppTimer == null) {
                    gAppTimer = new Timer(OnTimerTick, null, 60 * 1000, 60 * 1000);
                }
            }
        }
    }

    public static void StopTimer() {
        if (gAppTimer != null) {
            lock (lockObject) {
                if (gAppTimer != null) {
                    gAppTimer.Change(Timeout.Infinite, Timeout.Infinite);
                    gAppTimer = null;
                }
            }
        }
    }

    private static void OnTimerTick(object state) {
        Action();
    }

    public static void Action() {
        // Do what you need to do
    }
}

Just call SomeManager.StartTimer() from your first page or from App.xaml.cs and the timer will start.

Update

I updated the code a little:

  • Renamed the Initialize method to StartTimer.

  • Added StopTimer method which stops the timer. You can then start it again by calling SomeManager.StartTimer.

  • Added Action method which is the one actually donig the work. You can invoke it from anywhere, anytime.

    Note: the the timer will call this method in a background thread and you should do the same using something like Task.Run(() => SomeManager.Action());

  • Added a lock to ensure that the Start/Stop methods will not throw exceptions if invoked from multiple threads at the same time.

Upvotes: 2

Romasz
Romasz

Reputation: 29792

I'm not sure how you have arranged your code, but as I've tried:

public partial class App : Application
{
    public static PhoneApplicationFrame RootFrame { get; private set; }
    public DispatcherTimer gAppTimer = new DispatcherTimer();
    public void OnTimerTick(Object sender, EventArgs args)
    {
        MessageBox.Show("TIMER fired");
    }

    public App()
    {
        gAppTimer.Interval = TimeSpan.FromSeconds(2);
        // Sub-routine OnTimerTick that will be called at specified intervall
        gAppTimer.Tick += OnTimerTick;
        // starting the timer
        gAppTimer.Start();
        // rest of the code

the above code works. MessageBox shows every 2 seconds, if you had declared your DispatcherTimer as public, then you will be able to access it like this:

(App.Current as App).gAppTimer.Stop();

Note also that depending on what you want to achieve you may also use System.Threading.Timer.

On the other hand you may also think of using public static DispatcherTimer somewhere.

Upvotes: 0

Related Questions