Is there a rule when to use the native NSTimer
versus the .NET alternatives?
- System.Windows.Forms.Timer
- System.Timers.Timer
- System.Threading.Timer
Is there a rule when to use the native NSTimer
versus the .NET alternatives?
If you aim for portability, I'd use a .NET
timer (see below) except if you have no other choices (like a NSTimer
argument for a method call).
My all time favourite timer is unfortunately not listed in your question, is the one offered by the Task class:
await Task.Delay (20);
//do something after the delay
Usage is very simple. So instead of this Timer
code:
void f() {
var timer = new Timer(2000);
timer.Elapsed += OnTimerElapsed;
timer.Start ();
Console.WriteLine ("Timer started, control is back here");
}
void OnTimerElasped (object o, EventArgs e)
{
Console.WriteLine ("tick");
}
You can use this:
void f() {
StartTimer ();
Console.WriteLine ("Timer started, control is back here");
}
async void StartTimer ()
{
while (true) {
await Task.Delay (2000);
Console.WriteLine ("tick");
}
}
or if you want a single execution:
async void StartTimer ()
{
await Task.Delay (2000);
Console.WriteLine ("tick");
}
Which is a real benefit, as you don't need to keep the timer as instance variable just to be able to .Stop()
it.
I find this form more streamlined. Just like we dismissed the goto statement years ago (GOTO isn't dead. It's on the island with Elvis and Joe Dassin), it's time to think about our callbacks overuse.
I suggest to use NSTimer.
Xamarin 5.10:
var sampleTimer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (5.0), delegate {
//Write Action Here
});
and add a line To start the timer!
sampleTimer.Fire();
Stop after use:
sampleTimer.Invalidate ();
sampleTimer.Dispose ();
sampleTimer = null;
IMO the prime rule is that anytime some types (or methods) offers duplicated features between .NET and the platform you're currently working on, you must consider your long term cross-platform goals for your application and that particular bit of code (reuse).
IOW code using NSTimer
will only work on iOS and OSX. Using a .NET timer will work on Windows, Android and, of course, iOS and OSX.
Some answers recommend using .net timers for cross-platform goals. But the problem is that Timer
class is not available in some PCL profiles (at least the profile Xamarin uses). In those cases, the workaround involves using Task.Delay()
as @stephane-delcroix suggested. I even created a PclTimer
utility class for that matter.
BUT...
I found a situation where Task.Delay()
won´t work properly on iOS. If you try to use it within a background task:
var taskId = UIApplication.SharedApplication.BeginBackgroundTask(() => {});
// run your timer logic here with Task.Delay()
you´ll find out that the intervals become corrupted (delayed), not respecting the interval you set on Task.Delay(interval)
.
In that scenario, NSTimer.CreateRepeatingScheduledTimer()
works totally fine.
So I would say:
I agree with Poupou and Stephane, but I would also say "it depends". If you need to implement the timer in a common or shared part .Net alternatives are the best. Since the question is about Xamarin.iOS (not Xamarin.Android or Xamarin.Forms) I would like to add the following not listed (so far) solution that works for me and it's very simple.
NSTimer timer = NSTimer.CreateRepeatingScheduledTimer(TimeSpan.FromSeconds(3), delegate { MyMethod(); });
It Calls MyMethod(); every 3 seconds.