Фоновая задача приложения UWP останавливается при отключении мыши / клавиатуры

#c# #uwp #background-task

#c# #uwp #фоновая задача

Вопрос:

У меня есть приложение UWP, которое должно выступать в качестве информационного дисплея, который должен работать 24/7 в полноэкранном режиме. У меня есть фоновая задача, которая выполняет некоторые запросы rest, анализирует результат и передает его обратно в пользовательский интерфейс. Все работает так, как задумано.

НО!

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

Она может выполняться в течение нескольких дней, пока мышь / клавиатура подключены, но в ту же секунду, как я их отключаю, фоновая задача не выполняется.

Обрабатывает ли Windows отключение мыши / клавиатуры так, как если бы приложение теряло фокус и впоследствии приостанавливало всю фоновую работу?

Редактировать:

Вот как я создаю свою фоновую задачу:

     private async void MainPage_OnLoaded(object _sender, RoutedEventArgs _e)
    {
        var registration = BackgroundTaskRegistration.AllTasks.SingleOrDefault(_t => _t.Value.Name == BACKGROUND_TASK_NAME).Value;

        if (registration != null)
        {
            backgroundTask = (BackgroundTaskRegistration)registration;
            Logger.Information("Found background task with {ID} in application settings and found it registered, reusing it", backgroundTask.TaskId);
        }
        else
        {
            var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();

            Logger.Information("backGroundAccessStatus is {Status}", backgroundAccessStatus);

            if (backgroundAccessStatus == BackgroundAccessStatus.DeniedBySystemPolicy ||
                backgroundAccessStatus == BackgroundAccessStatus.DeniedByUser)
            {
                Logger.Error("Cannot create background task");
                return;
            }

            var builder = new BackgroundTaskBuilder
            {
                Name = BACKGROUND_TASK_NAME,
                TaskEntryPoint = TASK_ENTRY_POINT
            };

            builder.SetTrigger(fetchTrigger);
            backgroundTask = builder.Register();
            Logger.Information("Created a new Background task with id: {ID}", backgroundTask.TaskId);
        }

        backgroundTask.Completed  = BackgroundFetcher_Completed;
    }
  

Мой ApplicationTrigger запускается с помощью DispatcherTimer раз в 30 секунд. Запущенное событие выглядит следующим образом:

     private async void FetchTimerOnTick(object _sender, object _e)
    {
        var triggerResult = await fetchTrigger.RequestAsync();

        switch (triggerResult)
        {
            case ApplicationTriggerResult.Allowed:
                Logger.Information("Triggered fetching of data");
                break;
            case ApplicationTriggerResult.CurrentlyRunning:
                Logger.Information("Fetch task not complete yet. checking again in 30 sec");
                break;
            case ApplicationTriggerResult.DisabledByPolicy:
                Logger.Error("Fetch trigger disabled by policy");
                return;
            case ApplicationTriggerResult.UnknownError:
                Logger.Error("Fetch trigger had an unknown error");
                return;
        }
    }
  

Мой запуск для моей фоновой задачи выглядит следующим образом:

     public void Run(IBackgroundTaskInstance taskInstance)
    {
        Logger.Information("Background fetcher started");
        var deferral = taskInstance.GetDeferral();

        var timetableRequestTask = timeTablesModel.FetchTimeTables();
        var weatherRequestTask = weatherModel.FetchWeather();
        var newsRequestTask = newsTickerModel.FetchNews();

        Task.WaitAll(timetableRequestTask, weatherRequestTask, newsRequestTask);

        var fetchedData = new FetchedData
        {
            TimeTablesResponse = (TimeTablesResponse)timetableRequestTask.Result,
            WeatherUpdate = weatherRequestTask.Result,
            NewsResponse = (NewsResponse)newsRequestTask.Result
        };

        var path = $"{Path.GetTempPath()}BackgroundFetcherResultFile.json";

        using (var streamWriter = File.CreateText(path))
        {
            using (var jsonWriter = new JsonTextWriter(streamWriter))
            {
                var serializer = new JsonSerializer();
                serializer.Serialize(jsonWriter, fetchedData);
                jsonWriter.Flush();
            }
        }

        Logger.Information("Background fetcher completed");

        Task.Delay(TimeSpan.FromSeconds(5)).Wait();

        deferral.Complete();

    }
  

Событие для фоновой задачи.Завершено выглядит следующим образом:

     private async void BackgroundFetcher_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
    {
        Logger.Information("Background task completed");

        try
        {
            args.CheckResult();
        }
        catch (Exception e)
        {
            Logger.Error(e, "Exception occured in background task");
            return;
        }

        FetchedData fetchedData;
        var path = $"{Path.GetTempPath()}BackgroundFetcherResultFile.json";

        using (var streamReader = File.OpenText(path))
        {
            using (var jsonTextReader = new JsonTextReader(streamReader))
            {
                var serializer = new JsonSerializer();
                fetchedData = serializer.Deserialize<FetchedData>(jsonTextReader);
            }
        }

        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
         {
             if (fetchedData.TimeTablesResponse != null) timeTables.UpdateUi(fetchedData.TimeTablesResponse);

             var currentWeather = fetchedData.WeatherUpdate.CurrentWeather;
             var radar = fetchedData.WeatherUpdate.Radar;
             var forecast = fetchedData.WeatherUpdate.WeatherForecast;

             if (currentWeather != null) weather.UpdateCurrentWeatherUi(currentWeather);

             if (radar != null) weather.UpdateRadarUi(radar);

             if (forecast != null) weather.UpdateWeatherForecastUi(forecast);

             if (fetchedData.NewsResponse != null)
             {
                 news.UpdateNewsArticles(fetchedData.NewsResponse);
             }
         });
    }
  

Завершенное событие просто анализирует сгенерированный файл и представляет его в графическом интерфейсе.

Я вижу в журналах, что строка «Инициированная выборка данных» появляется неоднократно, но когда строка «Фоновая задача завершена» перестает печататься в моих журналах.

Комментарии:

1. Какой фоновый триггер вы использовали?

2. Запуск приложения. И я вызываю RequestAsync (), который возвращает ApplicationTriggerResult. Разрешено.

3. В общем случае отключение мыши / клавиатуры не повлияет ApplicationTrigger . И я также тестировал с официальным образцом кода, к сожалению, я не смог воспроизвести это. Лучший способ — предоставить мини-образец, который мог бы воспроизвести эту проблему для нас.

4. Я больше не знаю, что лучше или хуже! Я попытался воспроизвести ошибку с помощью кода примера BackgroundTask из GitHub и не смог этого сделать. Все работает так, как задумано. Я просмотрел свой код и сравнил его в основном построчно с примером и не нашел никакой ошибки. Я добавил режим ожидания в фоновом рабочем режиме, и внезапно он начал работать. Я понятия не имею, почему, но пока это работает, и я не собираюсь это трогать! 😛

5. Как только я закончил писать этот комментарий, он перестал работать!