Xamarin.forms - таймер работает медленнее, когда телефон заблокирован - PullRequest
0 голосов
/ 23 апреля 2020

У меня проблема с таймером в приложении Xamarin.Forms. Он работает нормально, когда экран включен, но когда я блокирую телефон, таймер работает значительно медленнее.

Это мой код

        internal void StartCountdown()
        {
            CancellationTokenSource CTS = _cancellationTokenSource;

            Device.StartTimer(new TimeSpan(0, 0, 1), () =>
            {
                if (CTS.IsCancellationRequested)
                {
                    return false;
                }

                if (0 < Time)
                {
                    --Time;
                    return true;
                }

                try
                {
                    var duration = TimeSpan.FromSeconds(1);
                    Vibration.Vibrate(duration);
                }
                catch (FeatureNotSupportedException)
                {
                    return true;
                }

                return false;
            });
        }

        internal void StopCountdown()
        {
            Interlocked.Exchange(ref _cancellationTokenSource, new CancellationTokenSource()).Cancel();
        }

Есть идеи, что происходит?

1 Ответ

0 голосов
/ 24 апреля 2020

Я нашел решение!

Мне пришлось использовать BackgroundServices от Xamarin.Forms.

Это решение для других:

В Android Основная активность:

        void WireUpLongRunningTask()
        {
            MessagingCenter.Subscribe<StartTimerTaskMessage>(this, "StartTimerTaskMessage", message => {
                var intent = new Intent(this, typeof(TimerService));
                intent.PutExtra("time", message.Time);
                StartService(intent);
            });

            MessagingCenter.Subscribe<StopTimerTaskMessage>(this, "StopTimerTaskMessage", message => {
                var intent = new Intent(this, typeof(TimerService));
                StopService(intent);
            });
        }

Метод вызова в OnCreate ();

Создание службы:

[Service]
    public class TimerService : Service
    {
        CancellationTokenSource _cts;

        public override IBinder OnBind(Intent intent)
        {
            return null;
        }

        public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
        {
            _cts = new CancellationTokenSource();

            Task.Run(() => {
                try
                {
                    var time = intent.GetIntExtra("time", 30);
                    var timer = new CountdownTimer();
                    timer.RunCounter(time, _cts.Token).Wait();
                    _cts.Cancel();
                }
                catch (Exception)
                {
                }
                finally
                {
                    if (_cts.IsCancellationRequested)
                    {
                        var message = new CancelledMessage();
                        Device.BeginInvokeOnMainThread(
                            () => MessagingCenter.Send(message, "CancelledMessage")
                        );
                    }
                }

            }, _cts.Token);

            return StartCommandResult.Sticky;
        }


        public override void OnDestroy()
        {
            if (_cts != null)
            {
                _cts.Token.ThrowIfCancellationRequested();

                _cts.Cancel();
            }
            base.OnDestroy();
        }
    }

IN PL C библиотека

ViewModel со счетчиком:


            MessagingCenter.Subscribe<TimerMessage>(this, "TickedMessage", message => {
                Device.BeginInvokeOnMainThread(() =>
                {
                    Time = message.Time;
                });
            });

            MessagingCenter.Subscribe<CancelledMessage>(this, "CancelledMessage", message => {
                Device.BeginInvokeOnMainThread(() => {
                    Time = SelectedTime;
                    IsCounting = false;
                });
            });

        internal void StartCountdown()
        {
            var message = new StartTimerTaskMessage(Time);
            MessagingCenter.Send(message, "StartTimerTaskMessage");
        }

        internal static void StopCountdown()
        {
            var message = new StopTimerTaskMessage();
            MessagingCenter.Send(message, "StopTimerTaskMessage");
        }

    {
        public async Task RunCounter(int time, CancellationToken token)
        {
            await Task.Run(async () =>
            {
                for (int i = time; i >= 0; i--)
                {
                    if (i != time)
                    {
                        await Task.Delay(1000).ConfigureAwait(false);
                    }
                    token.ThrowIfCancellationRequested();

                    var message = new TimerMessage(i);
                    Device.BeginInvokeOnMainThread(() => {
                        MessagingCenter.Send<TimerMessage>(message, "TickedMessage");
                    });

                    if (i == 0)
                    {
                        try
                        {
                            var duration = TimeSpan.FromSeconds(1);
                            Vibration.Vibrate(duration);
                        }
                        catch (FeatureNotSupportedException)
                        {
                            return;
                        }
                    }

                }
            }, token).ConfigureAwait(false);
        }
    }

и классы для обмена сообщениямиCenter

    public class StopTimerTaskMessage
    {
    }

    public class StartTimerTaskMessage
    {
        public int Time { get; set; }
        public StartTimerTaskMessage(int time)
        {
            Time = time;
        }
    }

    public class CancelledMessage
    {
    }

    public class TimerMessage
    {
        public int Time { get; set; }
        public TimerMessage(int time)
        {
            Time = time;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...