UWP后台任务HttpClient在设备屏幕关闭时失败

我正在开发专为手机设计的UWP应用程序。 它旨在与本地家庭网络上运行的服务器同步数据。 此同步可能需要相当长的时间,因此后台任务不是同步数据的最佳位置; 它可能需要超过我分配的30秒。 然而,这个想法是使用带有计时器触发器的后台任务; 它会调用服务器来检查是否有任何更新消耗,然后弹出一个Toast通知,询问它是否可以在前台运行以执行同步。

如果屏幕打开,代码效果很好。 但是如果屏幕关闭,那我就不会收到任何通知。 起初我以为timertrigger没有触发,但是每当它运行时我就会记录,当然,每隔15分钟按时运行一次。 我深入研究它,它失败了。 具体来说,它在网络呼叫上失败了; HttpClient.GetAsync,出现以下错误:

"The text associated with this error code could not be found.\r\n\r\nA connection with the server could not be established\r\n" 

现在我检查了服务器; 它正在运行。 我打开屏幕,代码突然再次运行。 我已将触发器设置为仅在未计量连接可用时运行:

  var status = await BackgroundExecutionManager.RequestAccessAsync(); if(status.In(BackgroundAccessStatus.DeniedBySystemPolicy, BackgroundAccessStatus.DeniedByUser)) { return; } var builder = new BackgroundTaskBuilder(); builder.Name = Constants.BackgroundTaskName; builder.SetTrigger(new TimeTrigger(15, false)); builder.AddCondition(new SystemCondition(SystemConditionType.FreeNetworkAvailable)); BackgroundTaskRegistration task = builder.Register(); 

所以我认为只有当Wifi可用时才会触发定时器。 但是当我实际使用此代码执行HTTP Get时:

  async protected override void OnBackgroundActivated(BackgroundActivatedEventArgs args) { if (BackgroundWorkCost.CurrentBackgroundWorkCost == BackgroundWorkCostValue.High) return; if (!NetworkInterface.GetIsNetworkAvailable()) return; base.OnBackgroundActivated(args); if (args.TaskInstance.Task.Name == Constants.BackgroundTaskName) { var cancel = new CancellationTokenSource(); args.TaskInstance.Canceled += (s, e) => { cancel.Cancel(); cancel.Dispose(); }; var deferral = args.TaskInstance.GetDeferral(); try { HttpClient client = GetClient(); var response = await client.GetAsync(ConstructUrl(client.BaseAddress, "updates"), cancel.Token); var info = await ParseHttpResponse(response); } catch { } finally { deferral.Complete(); } } 

现在有趣的是,NetworkInterface.GetIsNetworkAvailable()返回“true”,告诉我有一个可用的网络。 但是,当我拨打电话时,我得到“无法建立与服务器的连接”。 我不知道我在这里做错了什么。

有任何想法吗?

您很可能需要在后台任务注册中指定“IsNetworkRequested”,以便在连接待机期间(在屏幕关闭时发生)网络正常运行。

请参阅此处的文档: https : //docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.BackgroundTaskBuilder

虽然这是一个古老的问题,但至今仍然有效。我从这篇文章得到了答案HttpClient GetAsync在Windows 8的后台任务中失败了 ..

在此处为遇到此问题的未来开发人员添加答案。

HttpClient在调用方法时不起作用,因为后台任务不会等待HttpClient完成其任务并继续执行到流程的末尾,因此不会await它被实例化。

例如:

从后台任务类的Run(IBackgroundTaskInstance taskInstance)调用initiate()方法时,以下内容不起作用。

 //In Your background task class public void Run(IBackgroundTaskInstance taskInstance) { BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); initiate(); deferral.Complete(); } public async void initiate() { //some code HttpClient client = new HttpClient(); HttpResponseMessage responseMessage = await client.GetAsync(new Uri(url)); } 

解:

 //In Your background task class public async void Run(IBackgroundTaskInstance taskInstance) { BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); await initiate(); //Background task will wait for the initiate() to complete then call defferal.Complete(). deferral.Complete(); } public async Task initiate() { //some code HttpClient client = new HttpClient(); HttpResponseMessage responseMessage = await client.GetAsync(new Uri(url)); }