Is there a rule when to use the native NSTimer
versus the .NET alternatives?
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 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;
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With