Reputation: 20289
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:
Can I use BeginBackgroundTask
/EndBackgroundTask
everywhere in my application? Most examples only use this in DidEnterBackground
...
How does the system know where the beginning and the end of this background thread is?
Is the code between BeginBackgroundTask
and EndBackgroundTask
executed even UI related stuff is used?
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
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.
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