NSTimer против таймера в Xamarin.iOS - когда использовать что?

Есть ли правило, когда использовать родную NSTimer по сравнению с альтернативами .NET?

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

Ответ 1

IMO основное правило заключается в том, что в любое время некоторые типы (или методы) предлагают дублированные функции между .NET и платформой, на которой вы сейчас работаете, вы должны учитывать долгосрочные кросс-платформенные цели для своего приложения и этот конкретный бит код (повторное использование).

Код IOW с использованием NSTimer будет работать только на iOS и OSX. Использование таймера .NET будет работать на Windows, Android и, конечно же, на iOS и OSX.

Ответ 2

Если вы нацелены на переносимость, я бы использовал таймер .NET (см. ниже), за исключением случаев, когда у вас нет других вариантов (например, аргумент NSTimer для вызова метода).

Мой любимый таймер все время, к сожалению, не указан в вашем вопросе, это тот, который предлагается классом Task:

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

Использование очень простое. Поэтому вместо этого 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");
}

Вы можете использовать это:

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 не мертв, он на острове с Элвисом и Джо Дассином), пришло время подумать о том, что наши обратные вызовы злоупотребляют.

Ответ 3

Я предлагаю использовать NSTimer.

Xamarin 5.10:

var sampleTimer = NSTimer.CreateRepeatingScheduledTimer (TimeSpan.FromSeconds (5.0), delegate {

    //Write Action Here
                }); 

и добавьте строку. Чтобы запустить таймер!

sampleTimer.Fire();

Остановка после использования:

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

Ответ 4

Я согласен с Poupou и Stephane, но я также сказал бы "это зависит". Если вам нужно реализовать таймер в общей или разделяемой части. Альтернативные альтернативы являются лучшими. Поскольку вопрос касается Xamarin.iOS(а не Xamarin.Android или Xamarin.Forms), я хотел бы добавить следующее, не указанное (пока) решение, которое работает для меня, и это очень просто.

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

Он вызывает MyMethod(); каждые 3 секунды.

Ответ 5

В некоторых ответах рекомендуется использовать таймеры .net для кросс-платформенных целей. Но проблема в том, что класс Timer недоступен в некоторых профилях PCL (по крайней мере, используется профиль Xamarin). В этих случаях обходной путь включает использование Task.Delay(), как предлагал @stephane-delcroix. Я даже создал класс утилиты PclTimer.

НО...

Я нашел ситуацию, когда Task.Delay() не работает должным образом в iOS. Если вы попытаетесь использовать его в фоновой задаче:

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

вы узнаете, что интервалы становятся поврежденными (с задержкой), не соблюдая интервал, установленный вами на Task.Delay(interval).

В этом сценарии NSTimer.CreateRepeatingScheduledTimer() работает полностью нормально.

Итак, я бы сказал:

  • Вам нужно запустить таймер в фоновом задании? = > Использовать NSTimer
  • Вам не нужны фоновые задания? = > использовать .NET