Таймер PCL .NET 4.5

Я создаю кроссплатформенные приложения с помощью Xamarin и MvvmCross. Мне нужно вызывать сервер для обновлений каждую минуту (позже я перейду к push-уведомлениям), но я не могу настроить таймер в своем основном проекте. Я видел MvvmCross N + 42, но я считаю, что целевые проекты старше, что позволяет использовать таймер. Ниже моя целевая структура.

Есть ли лучший способ постоянно вызывать метод, который вызывает службу?

  • .NET Framework 4.5 и выше
  • Приложения Магазина Windows (Windows 8) и выше
  • Windows Phone 8
  • Xamarin.Android
  • Xamarin.iOS

person Community    schedule 16.01.2014    source источник
comment
Это может иметь значение: stackoverflow.com/questions/12555049/timer-in -переносная-библиотека   -  person Jason    schedule 16.01.2014
comment
Спасибо, я видел эту ветку, но я не могу ориентироваться на Windows 8.1 и выше из-за Xamarin.   -  person    schedule 16.01.2014
comment
Верно, но есть обходные пути, предложенные до упоминания о постоянном исправлении в 8.1. По крайней мере я так читал.   -  person Jason    schedule 16.01.2014
comment
Я попробовал некоторые обходные пути, создав .NET 4.0 PCL и создав там экземпляры таймера, но они, похоже, приводят к сбою моего приложения, которое я отлаживаю. Я не знаю, потому ли это, что я использую Xamarin с MVVMCross.   -  person    schedule 16.01.2014
comment
Я сделал большую ошибку, когда я не ссылался на проект. была плохой ошибкой   -  person    schedule 16.01.2014


Ответы (2)


Ответ @stevemorgan работает очень хорошо. Я создал утилиту Timer на основе этого кода, чтобы сделать ее более пригодной для повторного использования. Я также добавил параметр runOnce, который остановит таймер после первого тика.

public class PclTimer
{
    public bool IsRunning { get; private set; }

    public TimeSpan Interval { get; set; }
    public Action Tick { get; set; }
    public bool RunOnce { get; set; }
    public Action Stopped { get; set; }
    public Action Started { get; set; }

    public PclTimer(TimeSpan interval, Action tick = null, bool runOnce = false)
    {
        Interval = interval;
        Tick = tick;
        RunOnce = runOnce;
    }

    public PclTimer Start()
    {
        if (!IsRunning)
        {
            IsRunning = true;
            Started?.Invoke();
            var t = RunTimer();
        }

        return this;
    }

    public void Stop()
    {
        IsRunning = false;
        Stopped?.Invoke();
    }

    private async Task RunTimer()
    {
        while (IsRunning)
        {
            await Task.Delay(Interval);

            if (IsRunning)
            {
                Tick?.Invoke();

                if (RunOnce)
                {
                    Stop();
                }
            }
        }
    }
}

Я использую это в MvvmCross без проблем:

timer = new Timer(TimeSpan.FromSeconds(4), 
            () => ShowViewModel<UserMatchViewModel>(), true)
            .Start();
person xleon    schedule 13.11.2015

Вы всегда можете сделать это самостоятельно благодаря чуду async/await:

public async Task RunTimer()
{
    while(_timerRunning)
    {
        // Do Work
        // ...

        await Task.Delay(_timerInterval);
    }
}

Когда вы его вызываете, не ждите его. Он будет работать в фоновом потоке, и вы можете прервать цикл, установив поле _timerRunning из другого места (или уничтожив задачу, возвращенную из вызова).

person Steve Morgan    schedule 07.03.2015