0

So I have two buttons Start/Stop and start works fine because it starts at the beginning each time start is clicked, which is what I want. But I'm new to xamarin forms and don't entirely understand how to stop device.starttimer.

This is what I have currently and it's not working. (don't worry about the sound stuff)

//timer
    bool shouldRun = false;
    private void timer()
    {
        Device.StartTimer(TimeSpan.FromSeconds(3), () =>
        {
            // Do something
            label.Text = "Time is up!";
            //shows start button instead of stop button
            startButton.IsVisible = true;
            //hides stop button
            stopButton.IsVisible = false;
            return shouldRun;
        });
    }

    private void STOPButton_Clicked(object sender, EventArgs e)
    {
        //shows start button instead of stop button
        startButton.IsVisible = true;
        //hides stop button
        stopButton.IsVisible = false;
        //stops timer
        shouldRun = false;
        //stops sound
    }

    private void STARTButton_Clicked(object sender, EventArgs e)
    {
        //hides start button
        startButton.IsVisible = false;
        //shows stop button instead of start button
        stopButton.IsVisible = true;

        //starts timer from beginning

        timer();
        //starts sound from beginning
    }
3
  • When you return false from the Func<bool> the timer is stopped. Commented Oct 15, 2018 at 13:04
  • That's what I thought but the Stop button isn't working when I declare shouldRun = false. Commented Oct 15, 2018 at 13:24
  • After you declare shouldRun = false in the stop button, the timer delegate will run one more time at the end of its 3 second timer, if you do not want the label being set to "Time is up!", then you would need to perform a check of shouldRun before that and jump over that assignment (or perform an early exit, return false). Commented Oct 15, 2018 at 13:30

1 Answer 1

2
  1. You add a cancellation token source to the view running the timer

    private CancellationTokenSource cancellation;

  2. Adapt your StopButton code as follows:

    private void STOPButton_Clicked(object sender, EventArgs e)
    {
        startButton.IsVisible = true;
        //hides stop button
        stopButton.IsVisible = false;
        //stops timer
        if (this.cancellation != null)
            Interlocked.Exchange(ref this.cancellation, new CancellationTokenSource()).Cancel();
        shouldRun = false;
    }
    
  3. Finally in your timer delegate you create the cancellation token source

    CancellationTokenSource cts = this.cancellation = new CancellationTokenSource();
    Device.StartTimer(TimeSpan.FromSeconds(3), () =>
    {
        if (this.cancellation != null)
            Interlocked.Exchange(ref this.cancellation, new CancellationTokenSource()).Cancel();
        // Do something
        label.Text = "Time is up!";
        //shows start button instead of stop button
        startButton.IsVisible = true;
        //hides stop button
        stopButton.IsVisible = false;
        return shouldRun;
    });
    

Basically it is quite similar to the bool flag method, SushiHangover mentioned in his comment. However a cancellation source is thread safe, so you don't run into nasty race conditions when stopping your timer from a different thread.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.