locked
Timer in Portable Class Library? RRS feed

  • Question

  • User30998 posted

    I would like to access System.Threading.Timer in my PCL targeting iOS, Droid, and Windows under Xamarin 3. I can't get it to happen. I know Microsoft accidentally left it out at one point, but they've fixed that. Is there a way to get it?

    http://stackoverflow.com/questions/12555049/timer-in-portable-library

    Wednesday, May 28, 2014 10:39 PM

Answers

  • User352 posted

    http://iosapi.xamarin.com/?link=M%3aXamarin.Forms.Device.StartTimer

    We needed timers, so we thought maybe you would too.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, May 28, 2014 11:02 PM

All replies

  • User352 posted

    http://iosapi.xamarin.com/?link=M%3aXamarin.Forms.Device.StartTimer

    We needed timers, so we thought maybe you would too.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, May 28, 2014 11:02 PM
  • User25759 posted

    I have a simple implementation in https://github.com/jamesmontemagno/FrenchPressTimer

    Like you said they left it out from PCL :(

    Wednesday, May 28, 2014 11:24 PM
  • User1004 posted

    another option is to await on a Task.Delay() and eventually loop.

    Thursday, May 29, 2014 5:44 AM
  • User2029 posted

    It IS available in PCL. You need to target a profile containing .NET 4.5.1 + Win8.1 + WP8.1

    /// <summary>
    /// Missing from PCL, except if targeting .NET 4.5.1 + Win8.1 + WP8.1
    /// </summary>
    internal sealed class Timer : CancellationTokenSource
    {
        internal Timer(Action<object> callback, object state, int millisecondsDueTime, int millisecondsPeriod, bool waitForCallbackBeforeNextPeriod = false)
        {
            //Contract.Assert(period == -1, "This stub implementation only supports dueTime.");
    
            Task.Delay(millisecondsDueTime, Token).ContinueWith(async (t, s) =>
            {
                var tuple = (Tuple<Action<object>, object>) s;
    
                while (!IsCancellationRequested)
                {
                    if (waitForCallbackBeforeNextPeriod)
                        tuple.Item1(tuple.Item2);
                    else
                        Task.Run(() => tuple.Item1(tuple.Item2));
    
                    await Task.Delay(millisecondsPeriod, Token).ConfigureAwait(false);
                }
    
            }, Tuple.Create(callback, state), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
        }
    
        protected override void Dispose(bool disposing)
        {
            if(disposing)
                Cancel();
    
            base.Dispose(disposing);
        }
    }
    
    Thursday, May 29, 2014 3:31 PM
  • User28549 posted

    here's a Timer implementation that works with Profile78

    internal delegate void TimerCallback(object state);
    
    internal sealed class Timer : CancellationTokenSource, IDisposable
    {
        internal Timer(TimerCallback callback, object state, int dueTime, int period)
        {
            Contract.Assert(period == -1, "This stub implementation only supports dueTime.");
            Task.Delay(dueTime, Token).ContinueWith((t, s) =>
                {
                    var tuple = (Tuple<TimerCallback, object>)s;
                    tuple.Item1(tuple.Item2);
                }, Tuple.Create(callback, state), CancellationToken.None,
                                                    TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
                                                    TaskScheduler.Default);
        }
    
        public new void Dispose() { Cancel(); }
    }
    
    Thursday, May 29, 2014 5:30 PM
  • User39217 posted

    Microsoft has fixed the problem: stackoverflow.com/questions/12555049/timer-in-portable-library

    .NET 4.5.1 + Win8.1 + WP8.1 is no problem.

    But if I add Xamarin.Android and Xamarin.iOS the Timer is gone. Are there any plans getting this to work?

    Thursday, July 10, 2014 7:48 PM
  • User14 posted

    @FabianHger? any reason why the earlier suggestions didn't work for you (such as Xamarin.Forms Device.Timer)?

    Portable Class Library profiles are finicky... sometimes they don't intersect the way you expect them to. Profile151 (the combination you selected above) excludes all the Xamarin.Forms platforms: iOS, Android and Windows Phone Silverlight 8. I think they key difference is .NET 4.5.1 has stuff that is too new to run on all those, so it cannot be a part of your Portable Class Library's requirements.

    Xamarin.Forms uses Profile78 which uses .NET 4.5 and is compatible with all the target platforms. Unfortunately System.Threading.Timer is not in this profile, but hopefully one of these other options works for you.

    Thursday, July 10, 2014 8:43 PM
  • User28549 posted

    What @CraigDunn? said! Stick to Profile78 for the foreseeable future.

    Thursday, July 10, 2014 8:45 PM
  • User39217 posted

    Forms implementation is working for me, thank you.

    Wednesday, July 23, 2014 6:29 PM
  • User107010 posted

    Look no further, AdvancedTimer class works like a charm. https://www.nuget.org/packages/Mobilist.AdvancedTimer.Forms.Plugin/

    Tuesday, August 25, 2015 11:46 PM
  • User106639 posted

    +1 for advanced timer. I've been using it for months. It's way better than the other suggestions here imho

    Wednesday, August 26, 2015 6:48 AM
  • User52818 posted

    +1 for advanced timer. Device.StartTimer is useless without the fundamental features that the advanced timer has. Why can't Xamarin build that into Device.StartTimer and makes life for us programmers simpler? I seem to have to get third party plugins a lot because Xamarin only covers the very basics! At least in Forms.

    Tuesday, December 29, 2015 1:23 AM
  • User116733 posted

    Yep @CraigDunn Xamarin forms StartTimer only useful in very simple usage cases, you can't cancel or stop a time running for example. Am giving advanced timer a go looking pretty good so far.

    Tuesday, February 23, 2016 1:28 PM
  • User145502 posted

    Nope. Mobilist.AdvancedTimer.Forms.Plugin does NOT work in profile 111. Please advice.

    Friday, April 15, 2016 7:15 AM
  • User2029 posted

    Check my answer above. Still working.

    Friday, April 15, 2016 8:18 AM
  • User196941 posted

    Here's a fun C# trick. You can splice your own interface into an existing class very easily, you just have to make an interface and a wrapper class that implements your interface and inherits from the class you want to abstract.

    Our Timer interface:

    public interface ITimer
      {
        // unfortunately we have to use our own event args since we don't have access to the real one
        event EventHandler<ElapsedEventArgs> Elapsed;    
    
        bool AutoReset { get; set; }
        bool Enabled { get; set; }
        double Interval { get; set; }
    
        void Start();
        void Stop();
        void Reset();
      }
    
      public class ElapsedEventArgs
        : EventArgs
      {
        public ElapsedEventArgs(DateTime signalTime)
        {
          SignalTime = signalTime;
        }
    
        public DateTime SignalTime { get; private set; }
      }
    

    Now, on every platform where System.Timers.Timer is actually available, we implement our Timer wrapper along with a factory that's injected into the PCL. The one downside is that because we had to use our own version of event args in the interface, the wrapper has to forward events from the base class. Still, it's quite a bit cleaner than Advanced Timer (IMO).

    public sealed class Timer
        : System.Timers.Timer, ITimer
      {
        public new event EventHandler<ElapsedEventArgs> Elapsed;
    
        public Timer()
        {
          base.Elapsed += Base_Elapsed;
        }
    
        public Timer (double interval)
          : base(interval)
        {
          base.Elapsed += Base_Elapsed;
        }
    
        public void Reset()
        {
          Stop();
          Start();
        }
    
        private bool m_disposed = false;
        protected override void Dispose(bool disposing)
        {
          if (m_disposed)
          {
            return;
          }
    
          base.Elapsed -= Base_Elapsed;
          m_disposed = true;
    
          base.Dispose(disposing);
        }
    
        private void Base_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
          if (Elapsed != null)
          {
            Elapsed(this, new ElapsedEventArgs(e.SignalTime));
          }
        }
      }
    
    Saturday, April 16, 2016 2:42 AM
  • User240848 posted

    I found I could just write a wrapper class on top of Xamarin.Forms.StartTimer to extend it into something a little more smart.

    It's not the best but it works well for me and I don't have to mess around with anything outside of the PCL. (It's all shared code!)

    Here's the wrapper public class Timer { private double _interval; public double Interval { get { return _interval; } set { _interval = value; if (Enabled) { Start(); } } } private Action _callBack; public Action CallBack { get { return _callBack; } set { _callBack = value; if (Enabled) { Start(); } } } private TimerHolder timer = null; public Timer(double interval, Action callBack) { Interval = interval; CallBack = callBack; } public bool Enabled { get { return timer != null; } } public void Start() { Stop(); timer = new TimerHolder(Interval, CallBack); } public void Stop() { if (timer != null) { timer.Stop(); timer = null; } } } And the holder class (just place it in the same file) class TimerHolder { public bool Enabled { get; set; } public TimerHolder(double interval, Action callBack) { Enabled = true; Xamarin.Forms.Device.StartTimer(TimeSpan.FromMilliseconds(interval), delegate { if (Enabled) { callBack(); } return Enabled; }); } public void Stop() { Enabled = false; } }

    Thursday, July 28, 2016 2:13 AM
  • User180523 posted

    @TheRealJasonSmith @StephaneDelcroix @JamesMontemagno @danielrab

    I see this thread is a bit dated, but it is the one that most closely matches the issue and has more realistic advice.

    I notice that Microsoft recently released a NuGet for System.Timer to fill this need. Hooraay! https://www.nuget.org/packages/System.Threading.Timer/

    However... There seems to be a conflict with the Shim Nuget which a lot of us use to fill all the other holes and missing calls. https://www.nuget.org/packages/shim/

    Does anyone know a way to force the calling of System.Timer to come from the new Microsoft assembly/nuget and not from the Shim assembly?

    Wednesday, January 4, 2017 3:04 PM
  • User280923 posted

    This is not a solution for everyone, but in my case it works just fine.

    My solution works if you don't need an event to know if the timer has ended. In my case I am calling the same method over and over again to draw pins on a map, so in my "DrawPins method", I call "ExecuteIfMinutesPassed method".

    In my map class, I declared a DateTime variable:

    public DateTime? StartTime{ get; set; }

    When I needed to start my timer, I called it like this:

    if (!MyClass.StartTime.HasValue) MyClass.StartTime= DateTime.Now;

    And to check if it reached a limit, I called this:

    private void ExecuteIfMinutesPassed(int minutes) { if (!StartTime.HasValue) return; var limit = StartTime.Value.AddMinutes(minutes); if (limit > DateTime.Now) return; // do what you need here StartTime= DateTime.Now; }

    Tuesday, February 14, 2017 2:47 PM
  • User321390 posted

    Hi All Great Xamarin Developers, I am Xamarin beginner. I use the Countdown timer in my application using Mobilist.AdvancedTimer.Forms.Plugin in Xamarin.forms(PCL) In Xamarin.forms(PCL) I have an issue in that one. If we run the app 1st time It works fine. If I navigate to some other page and come again to the home page to timer Page I have the issue like no label timer found. I attach my Screens below. Please help to resolve the issue

    Thanks, Have a Great Day

    Tuesday, June 20, 2017 6:02 AM
  • User277209 posted

    Hi How to use timer in Xamarin.Native [Not ~~Xamarin.Forms~~] project ? Can someone please help me with a PCL implimentation targeting Android & iOS for a Xamarin.native application

    Tuesday, August 29, 2017 5:49 AM
  • User363257 posted

    Im in the same boat as you @Mukteswar did you figure out a solution?

    Thursday, January 11, 2018 9:46 PM