【问题标题】:NSTimer versus Timer in Xamarin.iOS - when to use what?Xamarin.iOS 中的 NSTimer 与 Timer - 何时使用什么?
【发布时间】:2013-10-08 09:58:13
【问题描述】:

在使用原生 NSTimer 与 .NET 替代品时是否有规则?

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

【问题讨论】:

    标签: c# xamarin.ios xamarin


    【解决方案1】:

    如果您以可移植性为目标,我会使用 .NET 计时器(见下文),除非您没有其他选择(例如方法调用的 NSTimer 参数)。

    很遗憾,我最喜欢的计时器没有在您的问题中列出,是 Task 类提供的计时器:

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

    用法很简单。所以代替这个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");
    }
    

    你可以用这个:

    void f() {
        StartTimer ();
        Console.WriteLine ("Timer started, control is back here");
    }
    
    async void StartTimer ()
    {
        while (true) {
            await Task.Delay (2000);
            Console.WriteLine ("tick");
        }
    }
    

    或者如果你想要一次执行:

    async void StartTimer ()
    {
        await Task.Delay (2000);
        Console.WriteLine ("tick");
    }
    

    这是一个真正的好处,因为您不需要将计时器保留为实例变量就可以.Stop()它。

    我发现这种形式更加精简。就像我们几年前驳回了 goto 声明(GOTO 并没有死。它与 Elvis 和 Joe Dassin 在岛上)一样,是时候考虑一​​下我们的回调过度使用了。

    【讨论】:

    • Task.Delay() 并不是真正的计时器,是吗?我的意思是,我无法真正安排事情。
    • 我看到它,并将其用作计时器。它可以安排要执行的代码(放置在等待之后)。它只是更加精简,无需委托。
    • 然后重复计时器将是 while(true) { await Task.Delay(20); }?
    • 有没有办法在你的例子中停止计时器?
    【解决方案2】:

    我建议使用 NSTimer。

    Xamarin 5.10:

    var sampleTimer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (5.0), delegate {
    
        //Write Action Here
                    }); 
    

    并添加一行来启动计时器!

    sampleTimer.Fire();
    

    使用后停止:

        sampleTimer.Invalidate ();
        sampleTimer.Dispose ();
        sampleTimer = null;
    

    【讨论】:

    • 出于兴趣,您选择 NSTimer 而不是 .net 计时器的原因是什么?
    【解决方案3】:

    IMO 的主要规则是,任何时候某些类型(或方法)在 .NET 和您当前正在使用的平台之间提供重复的功能时,您必须考虑您的长期跨平台目标您的应用程序和那段特定的代码(重用)。

    使用 NSTimer 的 IOW 代码仅适用于 iOS 和 OSX。使用 .NET 计时器将适用于 Windows、Android,当然还有 iOS 和 OSX。

    【讨论】:

    • James 关于自动释放池的回答是真的吗?
    • ThreadPool 已经在内部支持NSAutoreleasePool,并且在 5.2 中添加了对Thread 的支持,请参阅spouliot.wordpress.com/2011/12/01/threading-and-pooling OTOH 支持TaskBackgroundWorker 仍然需要特殊支持(重用同一线程需要排空池)forums.xamarin.com/discussion/6404/…
    • @poupou +1 我确定我不久前就读到过这个问题,但不确定它是否已得到解决。我已根据您的文档链接删除了我的答案:)
    【解决方案4】:

    一些答案​​建议使用 .net 计时器来实现跨平台目标。但问题是 Timer 类在某些 PCL 配置文件中不可用(至少 Xamarin 使用的配置文件)。在这些情况下,解决方法是按照@stephane-delcroix 的建议使用Task.Delay()。我什至为此创建了一个PclTimer utility class

    但是...

    我发现Task.Delay() 在 iOS 上无法正常工作。如果您尝试在后台任务中使用它:

    var taskId = UIApplication.SharedApplication.BeginBackgroundTask(() => {});
    // run your timer logic here with Task.Delay() 
    

    您会发现间隔已损坏(延迟),与您在 Task.Delay(interval) 上设置的间隔无关。

    在这种情况下,NSTimer.CreateRepeatingScheduledTimer() 工作得很好。

    所以我会说:

    • 您需要在后台任务中运行计时器吗? => 使用 NSTimer
    • 您不需要后台任务? => 使用 .NET

    【讨论】:

      【解决方案5】:

      我同意 Poupou 和 Stephane 的观点,但我也会说“视情况而定”。 如果您需要在公共或共享部分中实现计时器,.Net 替代方案是最好的。由于问题是关于 Xamarin.iOS(不是 Xamarin.Android 或 Xamarin.Forms)我想添加以下未列出(到目前为止)对我有用的解决方案,它非常简单。

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

      它调用 MyMethod();每 3 秒一次。

      【讨论】:

        猜你喜欢
        • 2011-04-11
        • 2020-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-24
        相关资源
        最近更新 更多