I'm working on a UWP app designed for phones. It's designed to sync data with a server running on your local home network. This syncing might take quite some time so a background task isn't the best place to sync the data; it'll probably take more than the 30 seconds I'm allotted. The idea, however, is to use a background task with a timer trigger; it'll call the server to check if there are any updates to consume and then pop up a toast notification asking if it can run in the foreground to perform the synchronization.
The code works great... if the screen is on. But if the screen is turned off, then I never get any notifications. At first I thought the timertrigger wasn't triggering, but I logged whenever it ran and sure enough, ir ran every 15 minutes on time. I looked deeper into it, and it's failing. Specifically, it's failing on the network call; HttpClient.GetAsync, with the following error:
"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"
Now I checked the server; it's running. I turn the screen on and the code suddenly works again. I've set up the trigger to only run when an unmetered connection is available:
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();
So I would think that the timer only gets triggered when the Wifi is available. But then when I actually perform the HTTP Get using this code:
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();
}
}
Now the funny thing is, NetworkInterface.GetIsNetworkAvailable() returns "true", telling me there's a network available. But still, when I make the call, I get "A connection with the server could not be established". I have no idea what I'm doing wrong here.
Any ideas?
It is very likely that you are required to specify "IsNetworkRequested" on your background task registration in order for the network to be functional during connected standby (which occurs while the screen is off).
Refer to the documentation here: https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.BackgroundTaskBuilder
Though this is an old Question, this is still valid as of today.. I got the answer from this post HttpClient GetAsync fails in background task on Windows 8 ..
Adding the answer here for future developers who run into this issue.
The
HttpClient
will not work when call to the method, in which it is instantiated is notawait
- ed as the background task will not wait for theHttpClient
to finish its task and continue execution to the end of the flow.For example:
The following won't work when the
initiate()
method is called from theRun(IBackgroundTaskInstance taskInstance)
of your background task class.Solution: