【发布时间】:2013-10-08 09:58:13
【问题描述】:
在使用原生 NSTimer 与 .NET 替代品时是否有规则?
- System.Windows.Forms.Timer
- System.Timers.Timer
- System.Threading.Timer
【问题讨论】:
标签: c# xamarin.ios xamarin
在使用原生 NSTimer 与 .NET 替代品时是否有规则?
【问题讨论】:
标签: c# xamarin.ios xamarin
如果您以可移植性为目标,我会使用 .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 在岛上)一样,是时候考虑一下我们的回调过度使用了。
【讨论】:
我建议使用 NSTimer。
Xamarin 5.10:
var sampleTimer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (5.0), delegate {
//Write Action Here
});
并添加一行来启动计时器!
sampleTimer.Fire();
使用后停止:
sampleTimer.Invalidate ();
sampleTimer.Dispose ();
sampleTimer = null;
【讨论】:
IMO 的主要规则是,任何时候某些类型(或方法)在 .NET 和您当前正在使用的平台之间提供重复的功能时,您必须考虑您的长期跨平台目标您的应用程序和那段特定的代码(重用)。
使用 NSTimer 的 IOW 代码仅适用于 iOS 和 OSX。使用 .NET 计时器将适用于 Windows、Android,当然还有 iOS 和 OSX。
【讨论】:
NSAutoreleasePool,并且在 5.2 中添加了对Thread 的支持,请参阅spouliot.wordpress.com/2011/12/01/threading-and-pooling OTOH 支持Task 和BackgroundWorker 仍然需要特殊支持(重用同一线程需要排空池)forums.xamarin.com/discussion/6404/…
一些答案建议使用 .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() 工作得很好。
所以我会说:
【讨论】:
我同意 Poupou 和 Stephane 的观点,但我也会说“视情况而定”。 如果您需要在公共或共享部分中实现计时器,.Net 替代方案是最好的。由于问题是关于 Xamarin.iOS(不是 Xamarin.Android 或 Xamarin.Forms)我想添加以下未列出(到目前为止)对我有用的解决方案,它非常简单。
NSTimer timer = NSTimer.CreateRepeatingScheduledTimer(TimeSpan.FromSeconds(3), delegate { MyMethod(); });
它调用 MyMethod();每 3 秒一次。
【讨论】: