The original UWP HttpClient task does not work when the device screen is off

I am working on a UWP application designed for phones. It is designed to synchronize data with a server running on the local home network. This synchronization can take a lot of time, so the background task is not the best place to synchronize data; it will probably take more than 30 seconds that are allotted to me. However, the idea is to use a background task with a timer; he will call the server to check if there are any updates to use, and then display a notification about the toast, asking if he can work in the foreground to complete the synchronization.

The code works fine ... if the screen is on. But if the screen is off, I never get any notifications. At first I thought that the timertrigger did not start, but I recorded every time it worked, and, of course, I ran every 15 minutes on time. I looked deeper into her, and it did not work out. In particular, it does not work on a 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 works. I turn on the screen and the code works again again. I set the trigger to run only when a contactless 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 think the timer only starts when Wi-Fi is available. But then, when I really do an HTTP Get with 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 that NetworkInterface.GetIsNetworkAvailable () returns "true", telling me about the presence of a network. But still, when I make a call, I get "Server connection could not be established." I have no idea what I'm doing wrong here.

Any ideas?

+5
source share
2 answers

It is very likely that you need to specify "IsNetworkRequested" when registering a background task so that the network functions while waiting for a wait (what happens when the screen is turned off).

Refer to the documentation here: https://docs.microsoft.com/en-us/uwp/api/Windows.ApplicationModel.Background.BackgroundTaskBuilder

+2
source

Although this is an old question, it is still relevant from today. I got a response from this post. HttpClient GetAsync crashes in a background job in Windows 8 ..

Adding an answer here is for future developers who are facing this issue.

HttpClient will not work when the call to the method in which it is created is not await - ed, because the background task does not wait for the HttpClient complete its task and continue execution to the end of the stream.

For instance:

The following will not work if the initiate() method is called from Run(IBackgroundTaskInstance taskInstance) your background task class.

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

Decision:

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

All Articles