Search code examples
c#xamlwindows-8timercountdown

Delay windows 8 app countdown timer c#


I have a windows 8 game app that uses a timer for each level and I am trying to the timer 3 seconds.

The code I have to start the timer works but I can't seem to delay the timer so that I display words to count it down.

Here is the code:

private async void timer_Tick(object sender, object e)
        {
            await
                Time.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low,
                    () =>
                    { Time.Text = string.Format("{0}:{1}", (Counter/60), (Counter%60).ToString().PadLeft(2, ' ')); });
            Counter--;
            await Task.Delay(3000);}}

so I put async there because I thought I should put await Task.Delay(3000); after counter to delay the timer but it doesn't work. I do not want to the WinRT Xaml toolkit countdown timer because I don't want the animation there.

Any suggestions on what I am doing wrong would be great!


Solution

  • So presumably you want to update the display every second, to get this countdown? But if I've understood, for some reason you want to delay everything by 3 seconds.

    If you want things to happen 3 seconds later than they're currently happening, the obvious solution is to program the timer so it calls you when you actually want it to:

    private DispatcherTimer t = new DispatcherTimer();
    private int Counter = 120;
    
    public MainPage()
    {
        InitializeComponent();
    
        t.Interval = TimeSpan.FromSeconds(4);
        t.Tick += timer_Tick;
        t.Start();
    }
    
    private void timer_Tick(object sender, object o)
    {
        t.Interval = TimeSpan.FromSeconds(1);
        Time.Text = string.Format("{0}:{1}", (Counter / 60), (Counter % 60).ToString().PadLeft(2, ' '));
        Counter--;
    }
    

    That makes the first tick take 4 seconds to arrive, and then adjusts the interval to 1 second. So you'll get ticks spaced at 1 second intervals, but everything will happen 3 seconds later than it otherwise would. (If set the tick interval to 1 initially, then the first tick would take 1 second to arrive, which is why you need a delay of 4 seconds initially - an initial tick of 3 would only delay things by 2 seconds.)

    However, if you need to do some things immediately, and some with a delay, one obvious way to do that would be just to adjust the count in your handler by 3 seconds:

    private const int LevelMaxTime = 120;
    private DispatcherTimer t = new DispatcherTimer();
    private int Counter = LevelMaxTime;
    
    public MainPage()
    {
        InitializeComponent();
    
        t.Interval = TimeSpan.FromSeconds(1);
        t.Tick += timer_Tick;
        t.Start();
    }
    
    private void timer_Tick(object sender, object o)
    {
        // Do the undelayed work here, whatever that is...
    
        // Next, we do the delayed work, if there is any yet.
        int effectiveCount = Counter + 3;
        if (effectiveCount <= LevelMaxTime)
        {
            Time.Text = string.Format("{0}:{1}", (effectiveCount / 60), (effectiveCount % 60).ToString().PadLeft(2, ' '));
        }
        Counter--;
    }
    

    This just takes the effective current time to be 3 seconds before what Current says it is, thus delaying everything by 3 seconds.

    You could do something more like your original code:

    private async void timer_Tick(object sender, object o)
    {
        // Wait for 3 seconds...for some reason
        await Task.Delay(TimeSpan.FromSeconds(3));
        Time.Text = string.Format("{0}:{1}", (Counter / 60), (Counter % 60).ToString().PadLeft(2, ' '));
        Counter--;
    }
    

    That's closer in spirit to what you wrote (as far as I can tell), only it works, but it seems unnecessarily convoluted. Why not just program the timer to call you at the right time, rather than getting callbacks at the wrong time and then trying to compensate? It's a timer. It'll call you when you tell it to!