Dan Underhill
Dan Underhill

Reputation: 327

How do I stop my C# timer with my Click event from a Xamarin button?

I have a working timer method that calls an API function to get new stock price data every 3 seconds. The method works fine and continually updates the data in my Xamarin form every 3 seconds. This method is called "RefreshData()" and I call it from the MainPage() class.

I have been trying to find a syntax to properly STOP the timer when my Xamarin Button object calls the Click handler ("Handle_Clicked").

I have tried the myTimer.Change method, the myTimer.Dispose method and the Timeout.Infinite approaches. They all seem easy, but my syntax must be wrong because those approaches either are not recognized as indicated with red underlines in Visual Studio, or they generate other errors.

I'm looking for some guidance on getting the correct, working syntax to turn this timer off, and/or potentially toggle it back on again.

Here is the clip of code that I have that works in all other regards...

Thanks for your help :)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using Xamarin.Forms;
    using System.Timers;

    namespace MyTimerTest
    {

        [System.ComponentModel.DesignTimeVisible(false)]
        public partial class MainPage : ContentPage
        {
            public MainPage()
            {
                InitializeComponent();
                LoadData(); // Loads the initial data when the page loads
                RefreshData(); // Calls the timer method which refreshes the data
            }

            void RefreshData() // Sets the timer to call the UpdateData method which calls the LoadData method to get fresh data and update the UI with it
            {
                int seconds = 3 * 1000;
                var myTimer = new System.Threading.Timer(UpdateData, null, 0, seconds);
            }
            public void UpdateData(object o)
            {
                LoadData(); // <-- call for JSON API data, works fine and updates accordingly to the timer
            }

            void Handle_Clicked(object sender, EventArgs e)
            {
                myTimer.Dispose(); // <-- Error: myTimer doesn't exist in current context
                // myTimer.Change(Timeout.Infinite, Timeout.Infinite)
            }
      }

Upvotes: 0

Views: 1105

Answers (2)

Dan Underhill
Dan Underhill

Reputation: 327

Thank you everyone... as per @Jason and @enigmativity, I went with the System.Timers.Timer methodology and got things to work, including a Xamarin button that toggles the AutoReset property of the timer (myTimer) to true/false, effectively turning the refresh off and then on again.

Here is the code that I got to work...

     public MainPage()
            {

                InitializeComponent();
                LoadData(); // Loads the initial data when the page loads
                RefreshData(); // Calls the timer method which refreshes the data
            }

            System.Timers.Timer myTimer;

            void RefreshData() // Sets the timer to call the UpdateData method which calls the LoadData method to get fresh data and update the UI with it
            {
                // Create a timer with a three second interval.
                myTimer = new System.Timers.Timer(3000);
                // Hook up the Elapsed event for the timer. 
                myTimer.Elapsed += UpdateData;
                myTimer.AutoReset = true;
                myTimer.Enabled = true;
            }
            public void UpdateData(Object source, ElapsedEventArgs e)
            {
                LoadData(); // <-- call for JSON API data, works fine and updates accordingly to the timer
            }

            void Handle_Clicked(object sender, EventArgs e) // <-- toggles the UpdateData method call to ON/OFF
            {
                if(myTimer.AutoReset == true)
                {
                    myTimer.AutoReset = false;
                }
                else
                {
                    myTimer.AutoReset = true;
                }
            }

Upvotes: 0

Jason
Jason

Reputation: 89214

declaring the timer this way makes it scoped to the LoadData method

void RefreshData() // Sets the timer to call the UpdateData method which calls the LoadData method to get fresh data and update the UI with it
            {
                int seconds = 3 * 1000;
                var myTimer = new System.Threading.Timer(UpdateData, null, 0, seconds);
            }

instead, declare it at the class level (outside of a specific method) so it will be accessible everywhere in the class

System.Threading.Timer myTimer;

scope is a general C# concept (really, a general programming concept) and not tied specifically to Xamarin

Also, as @enigmativity mentions, System.Timers.Timer is a lot more flexible. However, the scoping issue will still be relevant.

Upvotes: 2

Related Questions