Работа с таймерами в приложении Xamarin.Forms

111
18 ноября 2020, 21:50

В приложении Xamarin.Forms необходимо реализовать таймер, срабатывающий через заданный интервал времени. При срабатывании таймера должно появляться диалоговое окно-сообщение и срабатывать звуковой сигнал. Попробовал сделать двумя способами: 1) Использовать метод Device.StartTimer(TimeSpan interval, Func callback); 2) Использовать симуляцию таймера с помощью временной задержки Task.Delay() в вызванном асинхронно методе.

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

Прошу подсказать как сделать таймер, который будет работать при переходе на другую страницу приложения до полного закрытия приложения. Попробовал реализовать таймер внутри App.xaml.cs, но в таком случае не получается вызвать диалоговое окно с сообщением DisplayAlert()

Вот как сделано сейчас:

private async void AlarmTimer(string nameRecipe, string nameTimer, int interval)
{
    await Task.Delay(interval);
    DependencyService.Get<IAudio>().PlayAudioFile("alarm.mp3");
    await DisplayAlert("Таймер рецепта " + nameRecipe, "Cработал таймер " + nameTimer + " в " + DateTime.Now.ToString(), "Закрыть");
}

Установка таймера:

AlarmTimer(SelectedRecipe.Name, recipeTiming.Description, 5000);

Таймер работает если приложение находится на странице с таймером или странице, вызванной из неё. Но перестает работать при возврате на корневую страницу или предыдущую той, с которой идет вызов.

Думаю проблему бы решило размещение метода таймера на корневой странице и вызов его с вложенной страницы. Не могу только понять как в Xamarin.Forms правильно сделать такой вызов. Прошу подсказать

Answer 1

Пример решения через Device.StartTimer

Устройство вызывает Func callback каждые 5мс

    Device.StartTimer(TimeSpan.FromMilliseconds(5), OnTimerTick);

Реализация Func callback:

    private bool OnTimerTick()
    {
        bool alive = true;
        //Делаем что надо
        return alive;
    }

OnTimerTick - возвращает true - таймер продолжает работу, возвращает false - заканчивает работу.

Если ты вызываешь со страницы с таймером новую страницу, например:

    await Navigation.PushAsync(new SecondPage());

Таймер продолжает работу. Если нужно его отключать, делаешь это в OnAppearing и не забываешь запускать таймер при возврате на страницу в OnDisappearing(). При навигации, можно все таймеры оставить на корневой странице.

Малость о навигации https://metanit.com/sharp/xamarin/5.1.php

Вариант 2 - асинхронный метод While(timerEnable) и Task.Delay

async public void DrawTimer(int interval)
{
    if (await DisplayAlert("Подтвердите", "Запустить таймер?", "Да", "Нет"))
    {
        timerEnable = true;
        while (timerEnable)
        {
            DependencyService.Get<IAudio>().PlayAudioFile("alarm.mp3");
            await DisplayAlert("Таймер рецепта " + nameRecipe, "Cработал таймер " + nameTimer + " в " + DateTime.Now.ToString(), "Закрыть");
            //что-то делаем
            await Task.Delay(interval);
        }
    }
}
READ ALSO
Как подключиться из C# к другому .NET процессу?

Как подключиться из C# к другому .NET процессу?

Как средствами C# подключиться к другому процессу и мониторить некоторые данные из него? Известно, что исследуемое приложение так же написано...

137
Умирает объект созданный при помощи EasyHook

Умирает объект созданный при помощи EasyHook

Я немного не до понимаю время жизни меж-доменных объектов, они же MarshalByRefObject, но вот я поставил хук на IDirect3DDevice9::EndScene, далее происходит какое-то...

159
Получить AssemblyVersion из Assembly

Получить AssemblyVersion из Assembly

Можно ли получить AssemblyVersion из Assembly без загрузки ее в процесс(Из файла)?

140