views:

82

answers:

2

I am writing an app which uses a timer to display a countdown on screen to when some event happens. I want to reuse the timer, as it would be handy for a few things in the app, so I specify the words I want to wrap round the timer. For example, the following function call:

CountdownTimer(90, "You have ", " until the computer reboots");

would show:

You have 1 minute 30 seconds until the computer reboots

and then count down.

I am using the following code:

    private void CountdownTimer(int Duration, string Prefix, string Suffix)
    {
        Countdown = new DispatcherTimer();
        Countdown.Tick += new EventHandler(Countdown_Tick);
        Countdown.Interval = new TimeSpan(0, 0, 1);

        CountdownTime = Duration;
        CountdownPrefix = Prefix;
        CountdownSuffix = Suffix;
        Countdown.Start();
    }

    private void Countdown_Tick(object sender, EventArgs e)
    {
        CountdownTime--;
        if (CountdownTime > 0)
        {
            int seconds = CountdownTime % 60;
            int minutes = CountdownTime / 60;

            Timer.Content = CountdownPrefix;

            if (minutes != 0)
            {
                Timer.Content = Timer.Content + minutes.ToString() + @" minute";
                if (minutes != 1) { Timer.Content = Timer.Content + @"s"; }
                Timer.Content = Timer.Content + " ";
            }

            if (seconds != 0)
            {
                Timer.Content = Timer.Content + seconds.ToString() + @" second";
                if (seconds != 1) { Timer.Content = Timer.Content + @"s"; }
            }

            Timer.Content = Timer.Content + CountdownSuffix;

        }
        else
        {
            Countdown.Stop();
        }

    }

How do I make this run synchronously? For example I would want the following to wait 90 seconds and then reboot:

CountdownTimer(90, "You have ", " until the computer reboots");
ExitWindowsEx(2,0)

Whereas it calls the reboot immediately at present.

Any pointers would be most welcome!

Thanks,

Ben

+4  A: 

Personally, I'd recommend having a callback happen at the end of your CountdownTimer - perhaps taking an Action as an argument, such that when it completed it'd be called.

private Action onCompleted;
private void CountdownTimer(int Duration, string Prefix, string Suffix, Action callback)
{
    Countdown = new DispatcherTimer();
    Countdown.Tick += new EventHandler(Countdown_Tick);
    Countdown.Interval = new TimeSpan(0, 0, 1);

    CountdownTime = Duration;
    CountdownPrefix = Prefix;
    CountdownSuffix = Suffix;
    Countdown.Start();

    this.onCompleted = callback;
}
...
    else
    {
        Countdown.Stop();
        Action temp = this.onCompleted; // thread-safe test for null delegates
        if (temp != null)
        {
            temp();
        }
    }

Then you could just change your usage to:

CountdownTimer(90, "You have ", " until the computer reboots", 
    () => ExitWindowsEx(2,0));
mattdekrey
I like this answer +1
almog.ori
+1  A: 

You could use an AutoResetEvent:

System.Threading.AutoResetEvent _countdownFinishedEvent
    = new AutoResetEvent(false);

Add this at the end of CountdownTimer:

_countdownFinishedEvent.WaitOne();

And add this inside the else of Countdown_Tick just after Countdown.Stop():

_countdownFinishedEvent.Set();
Daniel Renshaw