2
votes

I'm writing a Xamarin Forms app and I need to call a REST service when the app is backgrounded. Should I use async/await or will this cause issues?

The scenario is a user adds a new item, has no network connection and closes the app. I need to repeatedly check for a network connection and, when one is available, post the new data to a REST service. To make matters worse, the data could include photos so could take a few minutes.

The solution I am attempting involves using a background fetch to check for a network connection then kick off a background safe task to do the heavy lifting. This is due to the 30 second limit on code run in a background fetch.

It all sounds good and my small test app seems to work. What I need help with is how to best use async/await to call the REST service.

Here is some code to show what the test app is doing

public override async void PerformFetch(UIApplication application, Action<UIBackgroundFetchResult> completionHandler)
{
    // kick off a long running task
    await StartLongRunningBackgroundTask();

    // this can be NoData, NewData or Failed
    completionHandler(UIBackgroundFetchResult.NoData);
}

public async Task StartLongRunningBackgroundTask()
{
    _backgroundTaskID = UIApplication.SharedApplication.BeginBackgroundTask(() => {
        // this is called if task times out
        if (_backgroundTaskID != 0)
        {
            UIApplication.SharedApplication.EndBackgroundTask(_backgroundTaskID);
            _backgroundTaskID = 0;
        }
    });

    try
    {
        var restService = FreshTinyIoCContainer.Current.Resolve<IRestClientService>();
        var result = await restService.GetDummyResult();

        var messagingService = FreshTinyIoCContainer.Current.Resolve<IMessagingService>();
        messagingService.Publish(new GotDataMessage { DataString = $"{result.foo} at {DateTime.Now:G}" });
    }

    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }

    UIApplication.SharedApplication.EndBackgroundTask(_backgroundTaskID);
}

I need to return from PerformFetch within 30 seconds. I'm not sure if await would do that or if I should call StartLongRunningBackgroundTask synchronously.

Any ideas? Anyone done this sort of thing before?

BTW on Android, I'm using the Firebase Job Dispatcher and all works well.

1

1 Answers

2
votes

Calling the REST service should always be done asynchronously. But if that call has a chance to take longer than the 30sec limit you should look at using the Background Transfer Service. You can setup the upload/download to run through a configured NSUrlSession. To get you started have a look at the walk through as well as this post. What you'll do basically is register the background task from your PerformFetch and iOS will schedule it to run.