#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. Как только я закончил писать этот комментарий, он перестал работать!