Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
AsyncTask in Android 4.0
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 1 - 25 of 46 - Collapse all  -  Translate all to Translated (View all originals)   Newer >
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Nathan  
View profile  
 More options Apr 20 2012, 3:16 pm
From: Nathan <nathan.d.mel...@gmail.com>
Date: Fri, 20 Apr 2012 12:16:35 -0700 (PDT)
Local: Fri, Apr 20 2012 3:16 pm
Subject: AsyncTask in Android 4.0

Still adjusting to the changes in Android 4.0 regarding AsyncTask.

If I understand right, the default behavior of execute is changing to one
single thread pool with only one thread? With the reason cited that
programmers are not capable of handling a bigger threadpool (I'm
paraphrasing).

Does that mean, that absent some code changes, all asynctasks inside a
process will only happen sequentially?  

So therefore, if I have a service running DownloadDictionaryTask in the
background, and the user chooses a menu item that starts
CheckDiskSpaceTask, the progress bar will cycle without any progress
because the task never makes progress?

A user and I could briefly reproduce a situation where, as far as I could
tell, no asynctasks were running, yet my AsyncTask would not even start. In
this case, I couldn't even get one thread. Alas, I cannot reproduce that
situation, which appeared to fix itself without any code changes.

But in any case, this isn't really acceptable to have only one asynctask
task run at once. But there is no central way to control that behavior, is
there? I would have to replace 83 instances of task.execute with
task.executeonExecutor. Since the above method is only available in SDK>11,
this isn't a one line change - it's more like 10-20 lines of code with
reflection, and some extensive testing.

In my opinion, this a deplorable punishment for those developers who have
dutifully followed the AsyncTask pattern, which, to this day, the Android
platform has encouraged.

Or perhaps I am reading this wrong. Maybe all DownloadDictionaryTasks share
one pool, and all CheckDiskSpaceTasks share another pool. In that case, the
rule is that only one task *of the same concrete type* can run at once.
This rule, I can probably live with, as I've used my own threading pools
for tasks that are truly data parallel.  

Can anyone enlighten me more?

Nathan


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kostya Vasilyev  
View profile  
 More options Apr 20 2012, 3:31 pm
From: Kostya Vasilyev <kmans...@gmail.com>
Date: Fri, 20 Apr 2012 23:31:01 +0400
Local: Fri, Apr 20 2012 3:31 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

The default, starting with 4.0, is to use the serial executor:

https://github.com/android/platform_frameworks_base/blob/master/core/...

But there is also an way to explicitly use the thread pool executor:

https://github.com/android/platform_frameworks_base/blob/master/core/...

i.e.:

new MyAsyncTask(....).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
....);

Or you could supply your own executor parameter that's constructed outside
of AsyncTask.

The predefined thread pool executor "constant" is new with API 11 (Android
3.0).

-- K

20 апреля 2012 г. 23:16 пользователь Nathan <nathan.d.mel...@gmail.com>написал:


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Murphy  
View profile  
 More options Apr 20 2012, 3:29 pm
From: Mark Murphy <mmur...@commonsware.com>
Date: Fri, 20 Apr 2012 15:29:24 -0400
Local: Fri, Apr 20 2012 3:29 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

On Fri, Apr 20, 2012 at 3:16 PM, Nathan <nathan.d.mel...@gmail.com> wrote:
> If I understand right, the default behavior of execute is changing to one
> single thread pool with only one thread?

I have not been able to confirm that this change is in place. When I
try testing a bunch of tasks, they seem to execute in parallel, even
on 4.0.3 (haven't tried 4.0.4 yet).

> Does that mean, that absent some code changes, all asynctasks inside a
> process will only happen sequentially?

Once this change takes effect (if it has not already), then yes.

> So therefore, if I have a service running DownloadDictionaryTask in the
> background, and the user chooses a menu item that starts CheckDiskSpaceTask,
> the progress bar will cycle without any progress because the task never
> makes progress?

Yes. Either use the supplied pooled executor with executeOnExecutor(),
or move one of those things out of AsyncTask (e.g.,
DownloadDictionaryTask might be better as an IntentService, if it is
supposed to keep rolling even if the user leaves the app).

> A user and I could briefly reproduce a situation where, as far as I could
> tell, no asynctasks were running, yet my AsyncTask would not even start. In
> this case, I couldn't even get one thread. Alas, I cannot reproduce that
> situation, which appeared to fix itself without any code changes.

If you come up with a reproducible scenario that demonstrates that the
default executor is the single-threaded one, I'd be interested in
taking a peek at it.

> But in any case, this isn't really acceptable to have only one asynctask
> task run at once. But there is no central way to control that behavior, is
> there? I would have to replace 83 instances of task.execute with
> task.executeonExecutor. Since the above method is only available in SDK>11,
> this isn't a one line change - it's more like 10-20 lines of code with
> reflection, and some extensive testing.

You wouldn't necessarily need to use reflection. Set your build target
to 11+ and create your own static execute() method somewhere that,
based on API level, uses execute() or executeOnExecutor() directly.
It's a code change, though, regardless.

Another possibility would be for you to grab an older AsyncTask out of
github.com/android, refactor it into your own package, and change your
import statements to use it instead of the stock AsyncTask.

> In my opinion, this a deplorable punishment for those developers who have
> dutifully followed the AsyncTask pattern, which, to this day, the Android
> platform has encouraged.

You certainly won't get any argument from me on this. My gast was most
certainly flabbered when Romain Guy mentioned this possibility a
year-plus ago.

> Or perhaps I am reading this wrong. Maybe all DownloadDictionaryTasks share
> one pool, and all CheckDiskSpaceTasks share another pool.

The pool is static at the AsyncTask level. Hence, all subclasses share
a single pool, unless I'm seriously missing something.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kostya Vasilyev  
View profile  
 More options Apr 20 2012, 3:55 pm
From: Kostya Vasilyev <kmans...@gmail.com>
Date: Fri, 20 Apr 2012 23:55:25 +0400
Local: Fri, Apr 20 2012 3:55 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

20 апреля 2012 г. 23:29 пользователь Mark Murphy
<mmur...@commonsware.com>написал:

> On Fri, Apr 20, 2012 at 3:16 PM, Nathan <nathan.d.mel...@gmail.com> wrote:
> > If I understand right, the default behavior of execute is changing to one
> > single thread pool with only one thread?

> I have not been able to confirm that this change is in place. When I
> try testing a bunch of tasks, they seem to execute in parallel, even
> on 4.0.3 (haven't tried 4.0.4 yet).

The default is definitely serial on my GNex with 4.0.2.

Did they revert it again for the 4.0.3 that you have?

-- K


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Murphy  
View profile  
 More options Apr 20 2012, 4:21 pm
From: Mark Murphy <mmur...@commonsware.com>
Date: Fri, 20 Apr 2012 16:21:41 -0400
Local: Fri, Apr 20 2012 4:21 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0
2012/4/20 Kostya Vasilyev <kmans...@gmail.com>:

> The default is definitely serial on my GNex with 4.0.2.

> Did they revert it again for the 4.0.3 that you have?

Here's how I am testing it (sloppy code, but it meets the need):

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;

public class ParallelTasksActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    new SillyTask().execute("A");
    new SillyTask().execute("B");
    new SillyTask().execute("C");
    new SillyTask().execute("D");
    new SillyTask().execute("E");
  }

  class SillyTask extends AsyncTask<String, String, Void> {
    @Override
    protected Void doInBackground(String... params) {
      for (int i=0; i < 5; i++) {
        String msg=params[0] + String.valueOf(i);

        Log.d("ParallelTasks", msg);
        SystemClock.sleep(1000);
      }

      return(null);
    }
  }

}

Now, if AsyncTask executes serially, I would expect:

A0
A1
A2
A3
A4
B0
B1
B2
B3
B4
...

Even if the letters were out of order (e.g., C before A), the
numerical index would be in order, because the task would be tying up
the one-and-only thread, so there should be no interleaving between
letter.

Yet, when I run this on 4.0.3 or 4.0.4, I get:

04-20 20:15:34.574: D/ParallelTasks(2965): D0
04-20 20:15:34.574: D/ParallelTasks(2965): C0
04-20 20:15:34.574: D/ParallelTasks(2965): E0
04-20 20:15:34.582: D/ParallelTasks(2965): A0
04-20 20:15:34.586: D/ParallelTasks(2965): B0
04-20 20:15:35.574: D/ParallelTasks(2965): D1
04-20 20:15:35.574: D/ParallelTasks(2965): E1
04-20 20:15:35.574: D/ParallelTasks(2965): C1
04-20 20:15:35.582: D/ParallelTasks(2965): A1
04-20 20:15:35.586: D/ParallelTasks(2965): B1
04-20 20:15:36.578: D/ParallelTasks(2965): E2
04-20 20:15:36.578: D/ParallelTasks(2965): C2
04-20 20:15:36.586: D/ParallelTasks(2965): D2
04-20 20:15:36.586: D/ParallelTasks(2965): A2
04-20 20:15:36.589: D/ParallelTasks(2965): B2
04-20 20:15:37.586: D/ParallelTasks(2965): C3
04-20 20:15:37.593: D/ParallelTasks(2965): D3
04-20 20:15:37.593: D/ParallelTasks(2965): B3
04-20 20:15:37.593: D/ParallelTasks(2965): E3
04-20 20:15:37.593: D/ParallelTasks(2965): A3
04-20 20:15:38.589: D/ParallelTasks(2965): C4
04-20 20:15:38.601: D/ParallelTasks(2965): D4
04-20 20:15:38.601: D/ParallelTasks(2965): E4
04-20 20:15:38.605: D/ParallelTasks(2965): B4
04-20 20:15:38.609: D/ParallelTasks(2965): A4

Since the five AsyncTask instances are interleaving their results, I
have to assume that they are running in parallel.

Even if I change doInBackground() to:

    @Override
    protected Void doInBackground(String... params) {
        Log.d("ParallelTasks", params[0] + " started");
        SystemClock.sleep(10000);
        Log.d("ParallelTasks", params[0] + " ended");

      return(null);
    }

so there's a 10-second tie-up, I get:

04-20 20:20:02.886: D/ParallelTasks(3044): D started
04-20 20:20:02.898: D/ParallelTasks(3044): B started
04-20 20:20:02.898: D/ParallelTasks(3044): A started
04-20 20:20:02.898: D/ParallelTasks(3044): E started
04-20 20:20:02.898: D/ParallelTasks(3044): C started
04-20 20:20:12.898: D/ParallelTasks(3044): A ended
04-20 20:20:12.902: D/ParallelTasks(3044): C ended
04-20 20:20:12.910: D/ParallelTasks(3044): D ended
04-20 20:20:12.914: D/ParallelTasks(3044): B ended
04-20 20:20:12.918: D/ParallelTasks(3044): E ended

All five start, 10 seconds elapses, and all five end, indicating that
they are running in parallel.

Where I am going wrong in my analysis?

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Nathan  
View profile  
 More options Apr 20 2012, 4:26 pm
From: Nathan <nathan.d.mel...@gmail.com>
Date: Fri, 20 Apr 2012 13:26:57 -0700 (PDT)
Local: Fri, Apr 20 2012 4:26 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

On Friday, April 20, 2012 12:29:24 PM UTC-7, Mark Murphy (a Commons Guy)
wrote:

> On Fri, Apr 20, 2012 at 3:16 PM, Nathan  wrote:
> > If I understand right, the default behavior of execute is changing to one
> > single thread pool with only one thread?

> I have not been able to confirm that this change is in place. When I
> try testing a bunch of tasks, they seem to execute in parallel, even
> on 4.0.3 (haven't tried 4.0.4 yet).

I don't download the source myself, but if this source listing is accurate,
it must be fully in place.

https://github.com/android/platform_frameworks_base/blob/master/core/...

> Yes. Either use the supplied pooled executor with executeOnExecutor(),
> or move one of those things out of AsyncTask (e.g.,
> DownloadDictionaryTask might be better as an IntentService, if it is
> supposed to keep rolling even if the user leaves the app).

I sure hope they won't be messing with the threadpool for intentservices
too.  

Nathan


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Nathan  
View profile  
 More options Apr 20 2012, 4:36 pm
From: Nathan <nathan.d.mel...@gmail.com>
Date: Fri, 20 Apr 2012 13:36:54 -0700 (PDT)
Local: Fri, Apr 20 2012 4:36 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

It's not quite so easy for a project that wants to run on pre 3.0
platforms. If you have an elegant solution for that, it will save me some
time.

Nathan


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Murphy  
View profile  
 More options Apr 20 2012, 4:34 pm
From: Mark Murphy <mmur...@commonsware.com>
Date: Fri, 20 Apr 2012 16:34:48 -0400
Local: Fri, Apr 20 2012 4:34 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

On Fri, Apr 20, 2012 at 4:26 PM, Nathan <nathan.d.mel...@gmail.com> wrote:
> I don't download the source myself, but if this source listing is accurate,
> it must be fully in place.

> https://github.com/android/platform_frameworks_base/blob/master/core/...

I've seen that, which is why I can't explain what I'm seeing at runtime.

> I sure hope they won't be messing with the threadpool for intentservices
> too.

IntentService does not have a thread pool. IntentService has always
had just one thread. Now, if you have several IntentServices in an
app, they will all have independent threads.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kostya Vasilyev  
View profile  
 More options Apr 20 2012, 4:44 pm
From: Kostya Vasilyev <kmans...@gmail.com>
Date: Sat, 21 Apr 2012 00:44:04 +0400
Local: Fri, Apr 20 2012 4:44 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

21 апреля 2012 г. 0:36 пользователь Nathan <nathan.d.mel...@gmail.com>написал:

> It's not quite so easy for a project that wants to run on pre 3.0
> platforms. If you have an elegant solution for that, it will save me some
> time.

Idea 1: Write a wrapper method in a utility class somewhere... replace
direct calls to execute with the one line call to this method

Idea 2: Use Mark's suggestion grab AsyncTask sources and embed it in your
own app so you'll have control over this.

Idea 3: Don't use AsyncTask... but then you'll need a replacement, and it's
probably easiest to use idea 2 rather than starting from scratch.

-- K


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kostya Vasilyev  
View profile  
 More options Apr 20 2012, 5:13 pm
From: Kostya Vasilyev <kmans...@gmail.com>
Date: Sat, 21 Apr 2012 01:13:17 +0400
Local: Fri, Apr 20 2012 5:13 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

"*Curiouser and curiouser*!" *Cried Alice*

Running your code on my GNex with official 4.0.2 I get this:

04-21 00:41:08.327 I/ParallelTasks(14355): A started
04-21 00:41:18.335 I/ParallelTasks(14355): A ended
04-21 00:41:18.335 I/ParallelTasks(14355): B started
04-21 00:41:28.335 I/ParallelTasks(14355): B ended
04-21 00:41:28.335 I/ParallelTasks(14355): C started
04-21 00:41:38.343 I/ParallelTasks(14355): C ended
04-21 00:41:38.343 I/ParallelTasks(14355): D started
04-21 00:41:48.335 I/ParallelTasks(14355): D ended
04-21 00:41:48.343 I/ParallelTasks(14355): E started
04-21 00:41:58.343 I/ParallelTasks(14355): E ended

Note the timestamps.

Here is my test, same idea really:

http://codetidy.com/2565/

and it also shows that the default execute() on my GNex with 4.0.2 is
serialized:

04-21 00:51:22.788 I/TestAsyncTask(14899): testDefaultExecutor
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 0
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 1
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 2
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 3
04-21 00:51:22.788 I/TestAsyncTask(14899): onPreExecute 4
04-21 00:51:22.788 I/TestAsyncTask(14899): doInBackground 0
04-21 00:51:27.796 I/TestAsyncTask(14899): doInBackground 1
04-21 00:51:32.796 I/TestAsyncTask(14899): doInBackground 2
04-21 00:51:37.796 I/TestAsyncTask(14899): doInBackground 3
04-21 00:51:42.804 I/TestAsyncTask(14899): doInBackground 4
04-21 00:51:47.804 I/TestAsyncTask(14899): done

04-21 00:51:47.804 I/TestAsyncTask(14899): testThreadPoolExecutor
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 0
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 1
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 2
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 3
04-21 00:51:47.804 I/TestAsyncTask(14899): onPreExecute 4
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 0
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 2
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 1
04-21 00:51:47.804 I/TestAsyncTask(14899): doInBackground 3
04-21 00:51:47.811 I/TestAsyncTask(14899): doInBackground 4
04-21 00:51:52.811 I/TestAsyncTask(14899): done

Again, note the timestamps (although the order is obvious).

On an Asus Tranformer with 4.0.3, I am getting the same results, the
default execute is serial.

Sanity check on a Sony Tablet S with 3.2.1, the default execute uses a
thread pool:

04-21 01:10:22.870 I/TestAsyncTask( 1002): testDefaultExecutor
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 0
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 1
04-21 01:10:22.880 I/TestAsyncTask( 1002): doInBackground 0
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 2
04-21 01:10:22.880 I/TestAsyncTask( 1002): onPreExecute 3
04-21 01:10:22.890 I/TestAsyncTask( 1002): onPreExecute 4
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 4
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 3
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 2
04-21 01:10:22.890 I/TestAsyncTask( 1002): doInBackground 1
04-21 01:10:27.890 I/TestAsyncTask( 1002): done

04-21 01:10:27.890 I/TestAsyncTask( 1002): testThreadPoolExecutor
04-21 01:10:27.890 I/TestAsyncTask( 1002): onPreExecute 0
04-21 01:10:27.890 I/TestAsyncTask( 1002): onPreExecute 1
04-21 01:10:27.890 I/TestAsyncTask( 1002): onPreExecute 2
04-21 01:10:27.900 I/TestAsyncTask( 1002): onPreExecute 3
04-21 01:10:27.900 I/TestAsyncTask( 1002): onPreExecute 4
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 0
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 1
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 3
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 4
04-21 01:10:27.900 I/TestAsyncTask( 1002): doInBackground 2
04-21 01:10:32.900 I/TestAsyncTask( 1002): done

04-21 01:10:32.900 I/ParallelTasks( 1002): A started
04-21 01:10:32.900 I/ParallelTasks( 1002): B started
04-21 01:10:32.910 I/ParallelTasks( 1002): D started
04-21 01:10:32.910 I/ParallelTasks( 1002): E started
04-21 01:10:32.910 I/ParallelTasks( 1002): C started
04-21 01:10:42.910 I/ParallelTasks( 1002): B ended
04-21 01:10:42.910 I/ParallelTasks( 1002): C ended
04-21 01:10:42.910 I/ParallelTasks( 1002): A ended
04-21 01:10:42.910 I/ParallelTasks( 1002): E ended
04-21 01:10:42.910 I/ParallelTasks( 1002): D ended

-- K

21 апреля 2012 г. 0:21 пользователь Mark Murphy
<mmur...@commonsware.com>написал:


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dianne Hackborn  
View profile  
 More options Apr 20 2012, 5:24 pm
From: Dianne Hackborn <hack...@android.com>
Date: Fri, 20 Apr 2012 14:24:34 -0700
Local: Fri, Apr 20 2012 5:24 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

Yes if your targetSdkVersion is >= 12, then as of that release the default
executor is serial.

This change was made because we realized we had a lot of bugs in the
platform itself where async tasks where created that had implicit ordering
dependences, so with the default parallel execution there were subtle rare
bugs that would result.

I can't address how much smarter you are than the rest of us, but I am
pretty convinced that for the vast majority of us the best thing to do is
have the default here be safe, allowing developers to change it for the
specific cases where they don't want that behavior.

This is a lesson I seem to learn every few years: multithreading is hard.
 Once you think you now understand it and are an expert, you are heading
soon to another painful lesson that multithreading is hard.

Having an API to set the default executor back to parallel is not a
solution, because it just gives you an easy way to create the exact same
problems we are trying to fix.  For example, if you have an async task that
executes due to some user input to update some data, there is a very very
good chance that if you allow these to be parallel you will have a bug.

Even with something as simple as a check box (which is one of the real
cases that drove this change) you can have this problem.  If you run an
executor to save to disk the new state of the check box, there *are*
situations where if you tap long enough and the CPU is loaded in the right
way, you will end up with the first state being saved after the second.

So, yes, the default is serial, and you must explicitly decide when to use
a parellel executor.  You should only use a parallel executor when you know
this is what you want and it is safe: when it is something that can take a
significant amount of time, and you know has no dependencies with any other
background tasks you may execute.  So in your example here, the solution is
to run your download task with AsyncTask.THREAD_POOL_EXECUTOR and leave the
others with the default serial executor.

--
Dianne Hackborn
Android framework engineer
hack...@android.com

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Murphy  
View profile  
 More options Apr 20 2012, 5:31 pm
From: Mark Murphy <mmur...@commonsware.com>
Date: Fri, 20 Apr 2012 17:31:57 -0400
Local: Fri, Apr 20 2012 5:31 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

On Fri, Apr 20, 2012 at 5:24 PM, Dianne Hackborn <hack...@android.com> wrote:
> Yes if your targetSdkVersion is >= 12, then as of that release the default
> executor is serial.

Bingo! It's the targetSdkVersion that's controlling the behavior.
Looking at the AsyncTask source code, I can't quite see how that's
happening, but at least I can confirm the results.

Though for me, the serialized behavior does not kick in until a
targetSdkVersion of 13 -- 12 still gives me parallel operation.

Thanks for the clarification!

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dianne Hackborn  
View profile  
 More options Apr 20 2012, 5:39 pm
From: Dianne Hackborn <hack...@android.com>
Date: Fri, 20 Apr 2012 14:39:51 -0700
Local: Fri, Apr 20 2012 5:39 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

Sorry yes it is API 13, I turned around the logic of the code when I
glanced at it:

        // If the app is Honeycomb MR1 or earlier, switch its AsyncTask
        // implementation to use the pool executor.  Normally, we use the
        // serialized executor as the default. This has to happen in the
        // main thread so the main looper is set right.
        if (data.appInfo.targetSdkVersion <=
android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }

On Fri, Apr 20, 2012 at 2:31 PM, Mark Murphy <mmur...@commonsware.com>wrote:

--
Dianne Hackborn
Android framework engineer
hack...@android.com

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kostya Vasilyev  
View profile  
 More options Apr 20 2012, 6:08 pm
From: Kostya Vasilyev <kmans...@gmail.com>
Date: Sat, 21 Apr 2012 02:08:10 +0400
Local: Fri, Apr 20 2012 6:08 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

Perhaps the documentation needs to be updated?

As of right now, it says:

"Note: this function schedules the task on a queue for a single background
thread or pool of threads *depending on the platform version*. "

... and makes no mention of the target sdk setting in the manifest.

Still, an app with targetSdkVersion 14 or 15 running on a 3.* device will
still be getting a pool of threads.

-- K

21 апреля 2012 г. 1:39 пользователь Dianne Hackborn
<hack...@android.com>написал:


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
b0b  
View profile  
 More options Apr 20 2012, 6:26 pm
From: b0b <pujos.mich...@gmail.com>
Date: Fri, 20 Apr 2012 15:26:26 -0700 (PDT)
Local: Fri, Apr 20 2012 6:26 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

On Friday, 20 April 2012 23:24:34 UTC+2, Dianne Hackborn wrote:

> Yes if your targetSdkVersion is >= 12, then as of that release the default
> executor is serial.

> This change was made because we realized we had a lot of bugs in the
> platform itself where async tasks where created that had implicit ordering
> dependences, so with the default parallel execution there were subtle rare
> bugs that would result.

While I understand why this change why made it introduced some subtle bugs
in apps running on ICS with the SerialExecutor vs the the Threaded Executor.
It is unfortunate and I'm not sure it was a wise decision to change such an
important behaviour that late.

Notably, lots of app uses AsyncTask to do networking I/O for which you can
spend quite a lot of time in doInBackground() for example if the connection
timeout or is
very slow. This is not uncommon on mobile networks.
Consider such an AsyncTask blocked for several seconds (maybe 20s or 30s)
in doInBackground(). With the serial executor it blocks *all pending*
AsyncTask in the queue until it finishes.
So it can give to the user the app is frozen or that something that should
happening or be updated isn't. That's a new kind of ANR without an actual
ANR.

To summarize, all apps who used AsyncTask assuming parallel execution are
possibly broken if doInBackground() does not finishes quick.
When I explained this to a well know Google engineer, I was told : "You
fool! thou shall use AsyncTask only for short lived task! Use your own
AsyncTask replacement for long-running parallel tasks".  Don't get even me
started on the scientific definition of "short lived task"...

In the end since I knew why I need the ThreadDed executor, I just wrapped
all my AsyncTask execution with this function:

static public <T> void executeAsyncTask(AsyncTask<T,?,?> task, T... params)
{
        if(isHoneycombOrLater()) {
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
        } else {
            task.execute(params);
        }
    }

Conclusion: there's probably man apps broken in subtle ways on ICS because
of this change.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Mark Murphy  
View profile  
 More options Apr 20 2012, 6:39 pm
From: Mark Murphy <mmur...@commonsware.com>
Date: Fri, 20 Apr 2012 18:39:58 -0400
Local: Fri, Apr 20 2012 6:39 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

On Fri, Apr 20, 2012 at 6:26 PM, b0b <pujos.mich...@gmail.com> wrote:
> Conclusion: there's probably man apps broken in subtle ways on ICS because
> of this change.

Probably not, only because they have to explicitly set the
targetSdkVersion to 13+, and I don't know how many people are setting
it that high.

That being said, it's a fairly significant change for something as
subtle as slightly increasing the targetSdkVersion, which is why we
need to make sure everyone knows about this. I agree with Kostya's
comment regarding docs -- at this point, I think an Android Developers
Blog post is probably needed.

--
Mark Murphy (a Commons Guy)
http://commonsware.com | http://github.com/commonsguy
http://commonsware.com/blog | http://twitter.com/commonsguy

_The Busy Coder's Guide to Android Development_ Version 3.7 Available!


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dianne Hackborn  
View profile  
 More options Apr 20 2012, 6:41 pm
From: Dianne Hackborn <hack...@android.com>
Date: Fri, 20 Apr 2012 15:41:06 -0700
Local: Fri, Apr 20 2012 6:41 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

2012/4/20 Kostya Vasilyev <kmans...@gmail.com>

> Perhaps the documentation needs to be updated?

Yes sorry it wasn't updated in ICS, I have it updated in the current dev
tree.

--
Dianne Hackborn
Android framework engineer
hack...@android.com

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dianne Hackborn  
View profile  
 More options Apr 20 2012, 6:42 pm
From: Dianne Hackborn <hack...@android.com>
Date: Fri, 20 Apr 2012 15:42:52 -0700
Local: Fri, Apr 20 2012 6:42 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

On Fri, Apr 20, 2012 at 3:26 PM, b0b <pujos.mich...@gmail.com> wrote:
> While I understand why this change why made it introduced some subtle bugs
> in apps running on ICS with the SerialExecutor vs the the Threaded Executor.
> It is unfortunate and I'm not sure it was a wise decision to change such
> an important behaviour that late.

We were very careful to not change the behavior for any existing apps.  It
only changes once you update your app and explicitly set your
targetSdkVersion to indicate you are compatible with the version of Android
where the change occurred.  This is standard practice we use frequently
when making changes to the platform that impact behavior applications may
be relying on.

--
Dianne Hackborn
Android framework engineer
hack...@android.com

Note: please don't send private questions to me, as I don't have time to
provide private support, and so won't reply to such e-mails.  All such
questions should be posted on public forums, where I and others can see and
answer them.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
b0b  
View profile  
 More options Apr 20 2012, 6:45 pm
From: b0b <pujos.mich...@gmail.com>
Date: Fri, 20 Apr 2012 15:45:33 -0700 (PDT)
Local: Fri, Apr 20 2012 6:45 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

To complete on this topic, I think it would be very useful to post an
article on this issue on the developer's blog,
asking developers whose app run on APi 13+ to review all their AsyncTask
execute() code to check
if it can use the default Executor or if it must use the Threaded Executor,
for example in the case of doing networking I/O or other possibly time
consuming tasks.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Nathan  
View profile  
 More options Apr 20 2012, 6:49 pm
From: Nathan <nathan.d.mel...@gmail.com>
Date: Fri, 20 Apr 2012 15:49:00 -0700 (PDT)
Subject: Re: [android-developers] AsyncTask in Android 4.0

B0b's concerns echo my own.

If you don't use an AsyncTask, you'll get an ANR. But if you do, you have a
progress bar that never moves because something else is running, and the
users will think it is frozen.

Nowhere have I been told that AsyncTasks were only for short lived tasks
(like a few seconds). I have used it for longer tasks. And I've never
really assumed that it was safe to use it for task with dependencies
between them.

If the platform is using the AsyncTask internally, it better be short lived
tasks.

Nonetheless, I can't disagree with Diane's lesson that multithreading is
hard. But the other thing I've learned about threads is that I always seem
to need more of them.  

Nathan


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
b0b  
View profile  
 More options Apr 20 2012, 6:52 pm
From: b0b <pujos.mich...@gmail.com>
Date: Fri, 20 Apr 2012 15:52:17 -0700 (PDT)
Local: Fri, Apr 20 2012 6:52 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

> > Conclusion: there's probably man apps broken in subtle ways on ICS
> because
> > of this change.

> Probably not, only because they have to explicitly set the
> targetSdkVersion to 13+, and I don't know how many people are setting
> it that high.

Bumping targetSdkVersion to the latest version is something very common and
generally harmless.

 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kostya Vasilyev  
View profile  
 More options Apr 20 2012, 6:50 pm
From: Kostya Vasilyev <kmans...@gmail.com>
Date: Sat, 21 Apr 2012 02:50:32 +0400
Local: Fri, Apr 20 2012 6:50 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

21 апреля 2012 г. 2:39 пользователь Mark Murphy
<mmur...@commonsware.com>написал:

> On Fri, Apr 20, 2012 at 6:26 PM, b0b <pujos.mich...@gmail.com> wrote:
> > Conclusion: there's probably man apps broken in subtle ways on ICS
> because
> > of this change.

> Probably not, only because they have to explicitly set the
> targetSdkVersion to 13+, and I don't know how many people are setting
> it that high.

I do for one of my apps :)

But then I don't use AsyncTask at all.

The thread pool thing seemed unrealiable to me back in the 2.* days...

Besides, my threading logic is typically either too simple for AsyncTask,
or too complex :)

-- K


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Kostya Vasilyev  
View profile  
 More options Apr 20 2012, 7:04 pm
From: Kostya Vasilyev <kmans...@gmail.com>
Date: Sat, 21 Apr 2012 03:04:12 +0400
Local: Fri, Apr 20 2012 7:04 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

21.04.2012 2:52 пользователь "b0b" <pujos.mich...@gmail.com> написал:

>> > Conclusion: there's probably man apps broken in subtle ways on ICS
because
>> > of this change.

>> Probably not, only because they have to explicitly set the
>> targetSdkVersion to 13+, and I don't know how many people are setting
>> it that high.

> Bumping targetSdkVersion to the latest version is something very common

and generally harmless.

Not sure I agree.

There are some subtle activity lifecycle callback changes starting with
3.0, some not so subtle home screen widget changes starting with 4.0...
just what comes to mind right away...


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
b0b  
View profile  
 More options Apr 20 2012, 7:07 pm
From: b0b <pujos.mich...@gmail.com>
Date: Fri, 20 Apr 2012 16:07:26 -0700 (PDT)
Local: Fri, Apr 20 2012 7:07 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

> To illustrate this further, consider this code from Tim Bray downlading
> images in a ListView. Something that must be implemented in thousand apps:

http://android-developers.blogspot.fr/2010/07/multithreading-for-perf...

This code running unmodified on ICS will download images sequencially
(instead of in parallel) and any timeouting download will block all other
downloads.

The fix  is just a matter of changing the Executor, but it illustrates
nicely the side effect of the change.


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Romain Guy  
View profile  
 More options Apr 20 2012, 7:07 pm
From: Romain Guy <romain...@android.com>
Date: Sat, 21 Apr 2012 01:07:54 +0200
Local: Fri, Apr 20 2012 7:07 pm
Subject: Re: [android-developers] AsyncTask in Android 4.0

> There are some subtle activity lifecycle callback changes starting with 3.0,
> some not so subtle home screen widget changes starting with 4.0... just what
> comes to mind right away...

And don't forget hardware acceleration that gets turned on when targetSdk=14+

--
Romain Guy
Android framework engineer
romain...@android.com


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Messages 1 - 25 of 46   Newer >
« Back to Discussions « Newer topic     Older topic »