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

时间:2016-08-24 21:58:52

标签: c# uwp windows-10-universal

我正在开发专为手机设计的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<UpdateInformation>(response);     
            }
            catch { }
            finally
            {
                deferral.Complete();
            }
        }

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

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

虽然这是一个古老的问题,但至今仍然有效。我从这篇文章中得到了答案HttpClient GetAsync fails in background task on Windows 8 ..

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

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

例如:

从后台任务类的initiate()调用Run(IBackgroundTaskInstance taskInstance)方法时,以下操作无效。

//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));      
}