testing
testing

Reputation: 20289

Correct implementation when using background safe task together with async/await

If the user presses the home button or is opening the app switcher or is receiving an incoming call a currently running task (web request) should get finished in background. I'm not using NSURLSession for this because I don't want to change the currently underlying class now. Therefore i want to make use of background-safe tasks.

I tried this:

public async Task retrieveCarList(){
    backgroundTaskID = UIApplication.SharedApplication.BeginBackgroundTask (() => {
        if(backgroundTaskID != 0){
            UIApplication.SharedApplication.EndBackgroundTask(backgroundTaskID);
            backgroundTaskID = 0;
        }
    });

    List<Car> carList = await manager.GetCarList();
    if(carList != null) {
        this.list = carList;
    } else {
        new UIAlertView("Error occurred", "", null, "OK", null).Show();
    }

    if(backgroundTaskID != 0){
        UIApplication.SharedApplication.EndBackgroundTask(backgroundTaskID);
        backgroundTaskID = 0;
    }
}

This seems to work, but I have to test it more.

Questions:

  1. Can I use BeginBackgroundTask/EndBackgroundTask everywhere in my application? Most examples only use this in DidEnterBackground ...

  2. How does the system know where the beginning and the end of this background thread is?

  3. Is the code between BeginBackgroundTask and EndBackgroundTask executed even UI related stuff is used?

  4. Is this the correct implementation after the blog post Multitasking in iOS: the MonoTouch way – Part I: Pressing the Home button but with async/await?

Edit 1:

Now I tried to work with Console.WriteLine. It seems that the await expression is executed but the code afterwards will be only executed if the user is opening the app again. What I'm worrying about is that EndBackgroundTask is only executed if the user is back at the app. Therefore the app could get killed if EndBackgroundTask is not called.

On the other side if I'm not using the background safe task the app is not doing the web request in background anymore if the home button is pressed. So it kind of works ...

How can I put all lines of code in the await expression? Then all code should get executed or?

Edit 2:

Putting the await expression in between an System.Action causes the app to crash and no error is shown. I also tried to use BeginBackgroundTask in retrieveCarList() and use EndBackgroundTask in the awaited GetCarList(), but the code is only executed if I'm back in the app. Additionally, I tried to wrap my await in another Task.Run, but this brings problems because I'm accessing UI related stuff which is not possible with this structure. My first try still seems to be the best, but it has the disadvantage stated above. If someone has a better implementation please post it.

Upvotes: 2

Views: 2734

Answers (1)

testing
testing

Reputation: 20289

Solutions:

1.) The Xamarin docs say that I can use this pattern everywhere. This is also stated in the Apple docs.

You can call this method at any point in your app’s execution.

2.) Dimitris Tavlikos states

It is after the BeginBackgroundTask call where your background time starts.

3.) The UI thread seems to be suspended according to Developing C# Apps for iPhone and iPad using MonoTouch: iOS Apps Development by Bryan Costanich.

4.) My approach seems to work fine. Now I put my Console.WriteLine before EndBackgroundTask and it is called like it should! Everything between BeginBackgroundTask and EndBackgroundTask is executed. Only the backgroundTaskID is not cleared, but other implementations also doesn't do this.

Upvotes: 3

Related Questions