How to use properly a Timer with thread ?

Hi everybody,

I would like to use a timer , to execute a time, pause and stop.

has spent several days that i search how to use in the best way a timer because, as you know, it does not exist a timer directly unless to create it.

so, I followed these informations by creating a timer, using a timespan, timercallback and stopwatch :

http://stackoverflow.com/questions/32050052/timer-doesnt-contain-in-system-threading-at-xamarin-forms

https://developer.xamarin.com/api/namespace/System.Timers/

https://developer.xamarin.com/api/type/System.Diagnostics.Stopwatch/

I think that stopwatch is the best. And with several manupulations, i have what i wanted, but the problem is that the time runs out that every time I press the run button, when I should press once on the button.

With a Thread too, I had done but it dis not change anything. I do not know why it do that.

And it is the same with a Datetime, I would like that the time of the Datetime continues to run while i did not press another button to stop it.

If someone would have an idea avout it, really thank you in advance.

Posts

  • AdamPAdamP AUUniversity ✭✭✭✭✭

    @UnityCenters - can you please post your code so we can see what is going on. When you post your code highlight it and press the 'C' button at the top of the text box to ensure your code is formatted correctly when posted.

  • UnityCentersUnityCenters USMember
    edited June 2016

    Hi, thanks for your reply.

    As I said, i think i have what i would. But I need to press just one time the button to run the chronometer instead of press it everytime with an incrementation of time milliseconds by milliseconds.

    So, here is my chronoTimer.cs for that :

    class TimerExpand
            {
                public int counter = 0;
                public System.Threading.Timer threadTimer;
            }
    
    
     public static void Temps()
            {
    
                TimerExpand t_expand = new TimerExpand();
    
                TimerCallback timerDelegate = new TimerCallback(GetTime);
    
                System.Threading.Timer timer = new System.Threading.Timer(timerDelegate, t_expand, 0, 1000);
    
                t_expand.threadTimer = timer;
    
    
           }
    
     public static void GetTime(object etat)
             {
               TimerExpand t_expand = (TimerExpand) etat;
                t_expand.counter++;
    
            }
    
    
        private DateTime actualDate;
         public static Stopwatch sw;
    
    And then on my buttonTimer_OnClicked method :
    
        actualDate = DateTime.Now;
         sw = new Stopwatch;
    
                    sw.Start();
    
        labelChrono.Text = string.Format("{0:00}:{1:00}:{2:00}:{3:00}", sw.Elapsed.Hours, sw.Elapsed.Minutes, sw.Elapsed.Seconds,
                       sw.Elapsed.Milliseconds);
    
     labelDate.Text = DateTime.Now.ToString();
    
                Temps();
    
    }
    
  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭
  • UnityCentersUnityCenters USMember

    Yes I already know that thing, it is not really what i search and I would like to use it on my others severals projects, but now anything can run with the file .winmd

    i have explained this here : https://forums.xamarin.com/discussion/68289/about-this-file-winmd#latest

    if someone know what it's that, i wound be really grateful.

  • UnityCentersUnityCenters USMember

    @AdamP , have you some ideas about this please ?

    thanks in advance.

  • UnityCentersUnityCenters USMember

    @AlessandroCaliaro I used the link but as i said, it is not really what i search, and it is does not work, when i run application, i have a system diagnostics exception which exit execution.

    @AdamP , i used many things with a DispatcherTimer, the Advancedtimer, the Device.BeginInvokedOnMainThread() method etc. but i do not get what i search, it is very important, I must have a timer in Xamarin this week.

    Why it is not the same thing as WPF ? it is could be more useful.

    thanks for any help

  • UnityCentersUnityCenters USMember

    So, if someone just know how to have that :: A kind of chronometer with possibility to start the time, to pause the time and to stop the time. Thank you so much, I would be really grateful.

    It is very urgent, thanks for any help.

  • JohnHardmanJohnHardman GBUniversity mod

    @UnityCenters - On what platforms does this need to work, how long might the chronometer need to run for, do you need the chronometer to keep running when backgrounded, and do you need any events triggered by the chronometer (e.g. an alarm time, or reaching zero if counting down). All of these could make a significant difference to what you need to do to implement it.

  • UnityCentersUnityCenters USMember

    @JohnHardman
    Hi , for the time the chronometer must run on Windows Platform. mobiles and tablettes. for duration, three hours maximum. In fact, i want to use it like for a chrono analysis you know ? user can start, make an action, pause if he need to do an other action and stop when all of the actions are finished with time displayed.

    Tell me if you need more informations and thanks for your message.

  • UnityCentersUnityCenters USMember

    @JohnHardman

    chronometer can keep running when backgrounded, user can for example write something in some entries like name of the operation, type of the operation, conditions of the operation etc. and press enter button for to save the datas on SQLite database.

    Thanks in advance

  • JohnHardmanJohnHardman GBUniversity mod
    edited June 2016

    @UnityCenters - Just to clarify - Windows mobiles and tablets, or also Android/iOS ?

    Will you just have start, pause and stop buttons, or will the chronometer be displayed as well, so that the user sees the elapsed duration going up? If you don't need to display the chronometer, you don't actually need a timer running at all, you could just get the current time when buttons are pressed and do some maths.

    If you do need to see the chronometer going up every second, but don't need it to trigger alarms etc., and if you just want this displayed on one page, then Device.StartTimer will be adequate. Something like the following should be the basis, but you will need to add the handlers for the buttons, and the maths for calculating time so far.

            // use 0.5 seconds to avoid jitter
            Device.StartTimer(TimeSpan.FromSeconds(0.5), () =>
            {
                if (!_keepTimerRunning) // simple way of cancelling timer
                    return false;
    
                DateTime nowUtc = DateTime.UtcNow;
    
        // optimisation to prevent unnecessary display updating
                if ((nowUtc.Second == _previousDateTime.Second)
                    && (nowUtc.Minute == _previousDateTime.Minute)
                    && (nowUtc.Hour == _previousDateTime.Hour))
                {
                    return true;
                }
    
                // update the display
                Device.BeginInvokeOnMainThread(() =>
                {
                    _timeRemainingValueLabel.Text = CalculatedTimeSoFar(nowUtc); // do the maths in here
    
                    // part of optimisation
                    _previousDateTime = nowUtc;
                }
    
                return true;
            });
    

    Remember that if your app is terminated whilst backgrounded, you will want to persist the time so far and the last start/re-start time (i.e. when start was pressed, whether initially or after a pause) prior to termination, so that you can add to it again when the app is re-loaded

    If you want to sound alarms etc as part of this, things get more complicated when handling backgrounding, particularly on iOS.

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    I'm using this - it works well - I briefly reviewed the code, it looks well written, no complaints so far.

  • UnityCentersUnityCenters USMember

    @PhilipOGorman , but you could not use pause button, only start and stop. And when i use it, in "AdvancedTimerImplementation.cs" i got error message on timer.Tick += e;

    and when i launch application, it does not run with an exception. So how do you use it or what are your modifications ?

    @PhilipOGorman , @JohnHardman

    I show you what i search

    I have one XAML page TimerChrono.xaml.

    on "TimerChrono.xaml"

    <?xml version="1.0" encoding="utf-8" ?>

    <Label x:Name="timeLabel" BackgroundColor="White" Text=" Durée " TextColor="Black" HorizontalTextAlignment="Center" FontSize="15"    >  </Label>
    
    
      <Button x:Name="stopChrono" BackgroundColor="Black" Text=" stop Chrono" Clicked="StopChrono_OnClicked" TextColor="Red" HorizontalOptions="Center">  </Button>
    
      <Button x:Name="pauseChrono" BackgroundColor="Black" Text=" pause Chrono" Clicked="PauseChrono_OnClickednClicked" TextColor="Gray" HorizontalOptions="Center">  </Button>
    

    on "TimerChrono.xaml.cs"

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;

    using Xamarin.Forms;

    namespace AdvancedTimer
    {
    public partial class TimerChrono : ContentPage
    {
    public TimerChrono()
    {
    InitializeComponent();

            if (startChrono.IsEnabled == true)
    
            {
                pauseChrono.IsEnabled = false;
                stopChrono.IsEnabled = false;
    
            }
    
        }
    

    private TimeSpan time;
    string Chrono;

        class TimerExpand
        {
            public int counter = 0;
            public Timer threadTimer;
        }
    
    
    
        public void Temps()
        {
    
            TimerExpand t_expand = new TimerExpand();
    
            TimerCallback timerDelegate = new TimerCallback(GetTime);
    
            Timer timer = new Timer(timerDelegate, t_expand, 0, 1000);
    
            t_expand.threadTimer = timer;
    
        }
    
    
    
        public void GetTime(object etat)
        {
            TimerExpand t_expand = (TimerExpand) etat;
            t_expand.counter++;
    
        }
    

    private DateTime actualDate;
    public static Stopwatch sw;

        private bool analyse = false;
    
    
    
    
        private void WaitThreadExecution(Action actionToExecute)
        {
            bool isFinished = false;
    
            Device.BeginInvokeOnMainThread(() =>
            {
                Temps();
                isFinished = true;
            });
    

    public void timerChrono()
    {

            var chrono = time += TimeSpan.FromMilliseconds(100);
    
            Chrono = chrono.TotalSeconds.ToString();
        }
    
    
    
    
    
    
        private async void StartChrono_OnClicked(object sender, EventArgs e)
        {
            analyse = true;
    
            pauseChrono.IsEnabled = true;
            stopChrono.IsEnabled = true;
    
    
            actualDate = DateTime.Now;
    
    
            sw = new Stopwatch();
    
    
        sw.Start();
    
            //  {
    
    
           var chrono = time += TimeSpan.FromMilliseconds(100);
    
            Chrono = chrono.TotalSeconds.ToString();
    
            //      labelChrono.Text = (actualDate - chrono).ToString();
    
            //      labelChrono.Text = string.Format("{0:00}:{1:00}:{2:00}:{3:00}", sw.Elapsed.Hours, sw.Elapsed.Minutes, sw.Elapsed.Seconds,
            //       sw.Elapsed.Milliseconds);
    
    
            labelChrono.Text = string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds,
                time.Milliseconds);
    
    
            //        labelChrono.Text = sw.Elapsed.Hours + sw.Elapsed.Minutes + sw.Elapsed.Seconds + sw.Elapsed.Milliseconds.ToString();
    
    
    
            // pour afficher la date
    
            labelDate.Text = DateTime.Now.ToString();
    

    }

    private void StopChrono_OnClicked(object sender, EventArgs e)
    {
    analyse = false;

            pauseChrono.IsEnabled = false;
            stopChrono.IsEnabled = false;
    
    
            // sw.Reset();
    
            sw.Stop();
    
    
            timeLabel.Text = string.Format("{0:00}:{1:00}:{2:00}:{3:00}", "Temps total :" + time.Hours, time.Minutes, time.Seconds,
               time.Milliseconds);
    
    
            labelDate.Text = "Date";
            labelChrono.Text = "Time";
      //      timeLabel.Text = "Durée";
    
        }
    
    
    
        private void PauseChrono_OnClickednClicked(object sender, EventArgs e)
    
        {
    
            analyse = false;
    
            timeLabel.Text = string.Format("{0:00}:{1:00}:{2:00}:{3:00}", "Temps total :" + time.Hours, time.Minutes, time.Seconds,
              time.Milliseconds);
    
        }
    
    
    
    }
    

    }

    And on "App.cs"

    MainPage = new NavigationPage(new TimerChrono());

    So, use this and you will see what i really search. Currently, you need to press everytime StartChrono button to run the timer instead of to press one time to run the timer without limit and to stop it or to pause it, when you want with the StopChrono button and PauseChrono button. 'Durée' on the application is the time elapsed.

    Please, tell me if you need more informations. I must make it run today , it is very important.

  • UnityCentersUnityCenters USMember

    Excuse , here it is the "TimerChrono.xaml"

    <?xml version="1.0" encoding="utf-8" ?>

    <Label x:Name="timeLabel" BackgroundColor="White" Text=" Durée " TextColor="Black" HorizontalTextAlignment="Center" FontSize="15"    >  </Label>
    
    
      <Button x:Name="stopChrono" BackgroundColor="Black" Text=" stop Chrono" Clicked="StopChrono_OnClicked" TextColor="Red" HorizontalOptions="Center">  </Button>
    
      <Button x:Name="pauseChrono" BackgroundColor="Black" Text=" pause Chrono" Clicked="PauseChrono_OnClickednClicked" TextColor="Gray" HorizontalOptions="Center">  </Button>
    

  • UnityCentersUnityCenters USMember

    it does want to be displayed or what

    here it is the "TimerChrono.xaml"

    <?xml version="1.0" encoding="utf-8" ?>

    <Label x:Name="timeLabel" BackgroundColor="White" Text=" Durée " TextColor="Black" HorizontalTextAlignment="Center" FontSize="15"    >  </Label>
    
    
      <Button x:Name="stopChrono" BackgroundColor="Black" Text=" stop Chrono" Clicked="StopChrono_OnClicked" TextColor="Red" HorizontalOptions="Center">  </Button>
    
      <Button x:Name="pauseChrono" BackgroundColor="Black" Text=" pause Chrono" Clicked="PauseChrono_OnClickednClicked" TextColor="Gray" HorizontalOptions="Center">  </Button>
    

  • UnityCentersUnityCenters USMember

    <Label x:Name="timeLabel" BackgroundColor="White" Text=" Durée " TextColor="Black" HorizontalTextAlignment="Center" FontSize="15"    >  </Label>
    
    
      <Button x:Name="stopChrono" BackgroundColor="Black" Text=" stop Chrono" Clicked="StopChrono_OnClicked" TextColor="Red" HorizontalOptions="Center">  </Button>
    
      <Button x:Name="pauseChrono" BackgroundColor="Black" Text=" pause Chrono" Clicked="PauseChrono_OnClickednClicked" TextColor="Gray" HorizontalOptions="Center">  </Button>
    

  • UnityCentersUnityCenters USMember

  • UnityCentersUnityCenters USMember

    I can not display all of the xaml page.

    so, you will make the startChrono button, the label labelDate with text="Date", and the label labelChrono with text = "Time"

    to use correctly my program. All of that, as you now, between , and .

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    @UnityCenters

    I'm sure you could modify the code to add pause. Here is how I use it:

    _connectionTimer.initTimer(10000, TimerCallback, false) _connectionTimer.stopTimer(); _connectionTimer.startTimer();

  • UnityCentersUnityCenters USMember

    For my message with xaml page. it is between a ScrollView and ContentPage.

    Ok, I will see that , but have you seen my program, just if you want to know what I search for the timer.

    you do not use label to see the chronometer ?

    Thanks for your message.

  • UnityCentersUnityCenters USMember

    @PhilipOGorman

    yes, I use it like that, but when I run the program, I got an exception on "App.g.i.cs" file on the line System.Diagnostics' and I do not know why. So, what is displayed when you run it ?

    @JohnHardman , have you seen my program to know what I really search ?

  • UnityCentersUnityCenters USMember

    @PhilipOGorman @JohnHardman Where are you ? have you seen my messages ? or do you need more informations on the program ?

    thanks in advance

  • UnityCentersUnityCenters USMember

    @JohnHardman , tell me if you need more informations for that. I just need to know how to run timer when i press one time on the start button and execution do not stop. But if I press on the stop button, execution stops. And if you see my program, I need to see on the page, timer in execution.

    Thanks in advance.

  • JohnHardmanJohnHardman GBUniversity mod

    @UnityCenters - As per my previous answer, as you don't seem to need anything (e.g. alarms, ticking sounds etc) happening whilst the app is backgrounded (or even terminated), Device.StartTimer together with persistence of the current state and the start time will suffice. The persistence is required, so that if your app is terminated whilst backgrounded, when the app is re-started, it can retrieve the date/time at which the user hit the start button and work out how long has elapsed, using this information to re-initialise the displayed timer value.

  • UnityCentersUnityCenters USMember

    But actually, the timer runs and anything is displayed even if there is something on .xaml page. It is because i already had what i search, and I just need to see timer in execution.

    Thanks for informations and message.

  • nattarSanthanarajnattarSanthanaraj USMember ✭✭

    Hi guys,
    I tried the Advanced timer. but I can't able to run. why does it happen like this?

  • SwathiSudarSwathiSudar USMember ✭✭

    Hi @AlessandroCaliaro
    I have error like in the below screen when I run the https://github.com/ufuf/AdvancedTimer

    How to figure it out the problem

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    which error? If you have an error in a plugin, you should open an Issue on GitHub

  • Hi,

    using Xamarin.Forms;
    using System;
    using System.Linq;
    using System.Diagnostics;

    namespace YourNamespace
    {
    public partial class App : Application
    {
    private static Stopwatch stopWatch = new Stopwatch();
    private const int defaultTimespan = 1;

        protected override void OnStart()
        {
            // On start runs when your application launches from a closed state, 
    
            if (!StopWatch.IsRunning)
            {
                StopWatch.Start();
            }
    
            Device.StartTimer(new TimeSpan(0, 0, 1), () =>
            {
                // Logic for logging out if the device is inactive for a period of time.
    
                if (StopWatch.IsRunning && StopWatch.Elapsed.Minutes >= defaultTimespan)
                {
                    //prepare to perform your data pull here as we have hit the 1 minute mark   
    
                        // Perform your long running operations here.
    
                        InvokeOnMainThread(()=>{
                            // If you need to do anything with your UI, you need to wrap it in this.
                        });
    
                    stopwatch.Restart();
                }
    
                // Always return true as to keep our device timer running.
                return true;
            });
        }
    
        protected override void OnSleep()
        {
            // Ensure our stopwatch is reset so the elapsed time is 0.
            StopWatch.Reset();
        }
    
        protected override void OnResume()
        {
            // App enters the foreground so start our stopwatch again.
            StopWatch.Start();
        }
    }
    

    }

    This is working perfectly for me.

Sign In or Register to comment.