我正在开发专为手机设计的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”,告诉我有可用的网络。但是,当我拨打电话时,我得到“无法建立与服务器的连接”。我不知道我在这里做错了什么。
有什么想法吗?
答案 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));
}