简体   繁体   English

Xamarin.iOS中的NSTimer与Timer - 何时使用什么?

[英]NSTimer versus Timer in Xamarin.iOS - when to use what?

Is there a rule when to use the native NSTimer versus the .NET alternatives? 是否有规则何时使用本机NSTimer与.NET替代品?

  • System.Windows.Forms.Timer System.Windows.Forms.Timer
  • System.Timers.Timer System.Timers.Timer
  • System.Threading.Timer System.Threading.Timer

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). 如果您的目标是可移植性,我将使用.NET计时器(见下文),除非您没有其他选择(如方法调用的NSTimer参数)。

My all time favourite timer is unfortunately not listed in your question, is the one offered by the Task class: 遗憾的是,我的所有时间最喜欢的计时器都未列在您的问题中,是Task类提供的计时器:

await Task.Delay (20);
//do something after the delay

Usage is very simple. 用法很简单。 So instead of this Timer code: 而不是这个Timer代码:

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. 这是一个真正的好处,因为您不需要将计时器作为实例变量,只是为了能够.Stop()它。

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. 就像我们多年前驳回goto声明一样(GOTO没有死。它与Elvis和Joe Dassin在岛上),现在是时候考虑我们的回调过度使用了。

I suggest to use NSTimer. 我建议使用NSTimer。

Xamarin 5.10: 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). IMO的主要规则是,无论何时某些类型(或方法)在.NET和您当前正在处理的平台之间提供重复功能,您必须考虑您的应用程序和特定代码的长期跨平台目标(重用) )。

IOW code using NSTimer will only work on iOS and OSX. 使用NSTimer IOW代码仅适用于iOS和OSX。 Using a .NET timer will work on Windows, Android and, of course, iOS and OSX. 使用.NET计时器可以在Windows,Android,当然还有iOS和OSX上运行。

I agree with Poupou and Stephane, but I would also say "it depends". 我同意Poupou和Stephane,但我也会说“这取决于”。 If you need to implement the timer in a common or shared part .Net alternatives are the best. 如果您需要在公共或共享部分中实现计时器.Net替代方案是最好的。 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. 由于问题是关于Xamarin.iOS(不是Xamarin.Android或Xamarin.Forms),我想添加以下未列出的(迄今为止)解决方案对我有用,而且非常简单。

NSTimer timer = NSTimer.CreateRepeatingScheduledTimer(TimeSpan.FromSeconds(3), delegate { MyMethod(); });

It Calls MyMethod(); 它调用MyMethod(); every 3 seconds. 每3秒钟一次。

Some answers recommend using .net timers for cross-platform goals. 一些答案建议使用.net计时器来实现跨平台目标。 But the problem is that Timer class is not available in some PCL profiles (at least the profile Xamarin uses). 但问题是Timer类在某些PCL配置文件中不可用(至少Xamarin使用的配置文件)。 In those cases, the workaround involves using Task.Delay() as @stephane-delcroix suggested. 在这些情况下,解决方法涉及使用Task.Delay()作为@ stephane-delcroix建议。 I even created a PclTimer utility class for that matter. 我甚至PclTimer创建了一个PclTimer实用程序类

BUT... 但...

I found a situation where Task.Delay() won´t work properly on iOS. 我发现Task.Delay()在iOS上Task.Delay()正常工作的情况。 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) . 你会发现间隔被破坏(延迟),而不是你在Task.Delay(interval)上设置的Task.Delay(interval)

In that scenario, NSTimer.CreateRepeatingScheduledTimer() works totally fine. 在那种情况下, NSTimer.CreateRepeatingScheduledTimer()完全正常。

So I would say: 所以我会说:

  • Do you need to run the timer in a background task? 你需要在后台任务中运行计时器吗? => Use NSTimer =>使用NSTimer
  • You don´t need background tasks? 你不需要后台任务吗? => use .NET =>使用.NET

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM