Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async/await bad practice under Android?

Currently I am porting an existing C# Windows 8 / iOS app to Android (with Xamarin).

I used a lot of async/await for file IO, dialogs, network, etc…

What happens when the app is paused/suspended during an await call? Under Windows and iOS there are two possibilities:

  • the app is resumed later, as if nothing had happened
  • the app is terminated if memory is low.

In both cases, there is no memoy leak, there are no changes in control flow.

However, under Android, an Activity can be destroyed and recreated while the process stays alive. In my understanding of async/await this means:

  • an unclosed dialog will wait forever, meaning that objects which were accessible from the caller ("this", local variables etc.) will stay in memory forever (memory leak)
  • when an awaited network request finishes while the former activity has already been destroyed by Android, the code after "await" (e.g. file write) could collide because two running instances of the Activity exist.

Are my assumtions true? If yes, what can be done? (without making the program as complicated as before of the invention of async/await)

like image 627
eikuh Avatar asked Mar 24 '14 14:03

eikuh


People also ask

Why you should avoid async void?

Async void methods can wreak havoc if the caller isn't expecting them to be async. When the return type is Task, the caller knows it's dealing with a future operation; when the return type is void, the caller might assume the method is complete by the time it returns.

Is it OK to not await async?

Using async void methods Every now and then you'll find yourself in a synchronous method (i.e. one that doesn't return a Task or Task<T> ) but you want to call an async method. However, without marking the method as async you can't use the await keyword. There are two ways developers work round this and both are risky.

Can async method return void?

In short, if your async method is an event handler or a callback, it's ok to return void .

Why async all the way?

So async all the way up enables you to actually make an asynchronous call and release any threads. If it isn't async all the way then some thread is being blocked. So unless you await all the way up, there's no benefit.


1 Answers

An Android Activity is guaranteed to call OnPause before the activity is deactivated/destroyed and OnResume when it starts up (see http://developer.android.com/training/basics/activity-lifecycle/index.html).

How about if you had a CancellationTokenSource available from your Activity. Then in OnPause you can call Cancel and then use:

try
{
    // Your async code
    ...
}
catch (OperationCancelledException e)
{
}

See also http://msdn.microsoft.com/en-us/library/jj155759.aspx for cancelling async tasks.

More a suggestion than a definitive answer, but I hope it helps.

Edit:

When I started introducing async/await into my code I found it to be like a zombie virus. Once you start asyncing you find it spreads throughout the rest of your code. It may be that you've got lots of async calls for the same reason. There are generally two rules to follow:

  1. Declare methods as public async Task Foo() instead of public async void Foo()
  2. Don't block on async code

In my own practice, I've discovered 2 places where you can break these general rules.

  1. If you're at the 'top' (i.e. the UI) of your code, there may be places where you have to declare code as async void because the delegate you're overriding takes void as a return type. A typical example of this is with a button.Click method.
  2. I had a database call which looked up a single value in a database. If I converted that to async, lots of my code elsewhere would have to change. I discovered that if you're guaranteed, and I mean guaranteed, to be at the 'bottom' of your code, specifically that none of the methods below the one you're calling use async, then you can safely call .Result on a Task. This saved me from asyncing half my code unnecessarily.

Hope this helps.

like image 131
Dave Avatar answered Oct 03 '22 06:10

Dave