[UWP] Фоновая задача прекращается через ~10-20 минут (загрузка файлов)

Я синхронизирую файлы в приложении UWP. Я использую фоновую задачу и ApplicationTrigger. Если я отлаживаю свой код (я имею в виду, если отладчик подключен), он работает, но если я запускаю установленное приложение, фоновая задача завершается через 10-20 минут. Я должен синхронизировать много файлов, и это займет 1-2 часа (я знаю, что это безумие). Я нашел информацию здесь: https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/handle-a-cancelled-background-task, но я не уверен, что это так, потому что все с памятью в порядке.

"Примечание. Для всех семейств устройств, кроме настольных, если на устройстве не хватает памяти, фоновые задачи могут быть прекращены. Если исключение нехватки памяти не обнаружено, или приложение не обрабатывает его, то фоновая задача будет завершена без предупреждения и не вызывая событие OnCanceled. Это помогает обеспечить удобство работы приложения на переднем плане. Ваша фоновая задача должна быть разработана с учетом этого сценария."

    public async void Run(IBackgroundTaskInstance taskInstance)
    {
        deferral = taskInstance.GetDeferral();
        _taskInstance = taskInstance;

        var details = taskInstance.TriggerDetails as ApplicationTriggerDetails;

        IEnumerable<string> filesUrls = details.Arguments.Select(x => x.Value as string).Distinct().ToList();
        filesCount = filesUrls.Count();

        downloader = CompletionGroupTask.CreateBackgroundDownloader();

        var result = await Download(filesUrls, taskInstance, downloader);
        if (result)
        {
            await Download(failedDownloads, taskInstance, downloader);
        }
        downloader.CompletionGroup.Enable();
        deferral.Complete();
    }

    private async Task<bool> Download(IEnumerable<string> filesUrls, IBackgroundTaskInstance taskInstance, BackgroundDownloader downloader)
    {
        bool downloadFailed = false;
        failedDownloads = new List<string>();
        foreach (string url in filesUrls)
        {
            DownloadOperation download = null;
            var uri = new Uri(url);
            try
            {
                download = downloader.CreateDownload(uri, await CreateResultFileAsync(url.Split('/').Last()));
                Task<DownloadOperation> startTask = download.StartAsync().AsTask();
                await startTask.ContinueWith(task => OnDownloadCompleted(task, url));
            }
            catch
            {
                downloadFailed = true;
                failedDownloads.Add(url);
            }
        }
        return downloadFailed;
    }


    private void OnDownloadCompleted(Task<DownloadOperation> task, string url)
    {
        if (task.Status == TaskStatus.RanToCompletion)
        {
            completedDownloads++;
            decimal progress = (completedDownloads / filesCount) * 100;
            _taskInstance.Progress = Convert.ToUInt32(progress);

        }
        else if(task.Status == TaskStatus.Faulted)
        {
            failedDownloads.Add(url);
        }
    }

    private async Task<IStorageFile> CreateResultFileAsync(string fileName)
    {
        var local = ApplicationData.Current.LocalFolder;
        IStorageFile resultFile = await local.CreateFileAsync(fileName, CreationCollisionOption.FailIfExists);
        return resultFile;
    }
}

Кто-нибудь знает, почему моя задача убита?

2 ответа

Обновлен для Обновления Создателя

В настоящее время существует ограниченная возможность, называемая extendedBackgroundTaskTime, которую можно использовать, чтобы при необходимости запускать фоновый процесс в течение 1-2 часов. Он не будет принят в Магазин Windows, но работает для загруженных приложений Line-Of-Business и отправки в Магазин Windows для бизнеса: https://docs.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations

В настоящее время нет способа запустить по-настоящему безголовую фоновую синхронизацию в течение 1–2 часов для приложения, представленного в Магазине. Синхронизация такого типа может выполняться асинхронно и частями. Классы BackgroundUploader и BackgroundDownloader являются опциями для передачи по сети отдельных файлов, а затем просыпаются, чтобы выполнить работу на основе завершения загрузки каждого из этих файлов. Если синхронизация может подождать, пока устройство не будет подключено к сети переменного тока, можно также зарегистрировать триггер обслуживания для периодического пробуждения и запуска в течение 10 минут для выполнения части работы по синхронизации.

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

Ваша фоновая задача отменяется с помощью BackgroundTaskCancellationReason = ExecutionTimeExceeded, поскольку максимально допустимое время для запуска фоновой задачи с ApplicationTrigger составляет 10 минут, если приложение работает. Если приложение приостановлено, фоновая задача с ApplicationTrigger может выполняться максимум 5 минут. Если этот срок достигнут, ОС отменит задание с помощью BackgroundTaskCancellationReason = IdleTask.

В вашей фоновой задаче поместите этот код в начало метода Run, чтобы увидеть причину отмены в тосте.

        taskInstance.Canceled += (s, e) => {
            var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
            var toastTextElements = toastXml.GetElementsByTagName("text");
            toastTextElements[0].InnerText = e.ToString();
            ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastXml));
        };
Другие вопросы по тегам