How to Run The Same Asynctask More Than Once

Is it possible to run multiple AsyncTask in same time?

use executor as follows

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new Save_data().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, location);
} else {
new Save_data().execute(location);
}

See this

Running multiple AsyncTasks at the same time -- not possible?

AsyncTask uses a thread pool pattern for running the stuff from doInBackground(). The issue is initially (in early Android OS versions) the pool size was just 1, meaning no parallel computations for a bunch of AsyncTasks. But later they fixed that and now the size is 5, so at most 5 AsyncTasks can run simultaneously. Unfortunately I don't remember in what version exactly they changed that.

UPDATE:

Here is what current (2012-01-27) API says on this:

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. After HONEYCOMB, it is planned to change this back to a single thread to avoid common application errors caused by parallel execution. If you truly want parallel execution, you can use the executeOnExecutor(Executor, Params...) version of this method with THREAD_POOL_EXECUTOR; however, see commentary there for warnings on its use.

DONUT is Android 1.6, HONEYCOMB is Android 3.0.

UPDATE: 2

See the comment by kabuko from Mar 7 2012 at 1:27.

It turns out that for APIs where "a pool of threads allowing multiple tasks to operate in parallel" is used (starting from 1.6 and ending on 3.0) the number of simultaneously running AsyncTasks depends on how many tasks have been passed for execution already, but have not finished their doInBackground() yet.

This is tested/confirmed by me on 2.2. Suppose you have a custom AsyncTask that just sleeps a second in doInBackground(). AsyncTasks use a fixed size queue internally for storing delayed tasks. Queue size is 10 by default. If you start 15 your custom tasks in a row, then first 5 will enter their doInBackground(), but the rest will wait in a queue for a free worker thread. As soon as any of the first 5 finishes, and thus releases a worker thread, a task from the queue will start execution. So in this case at most 5 tasks will run simultaneously. However if you start 16 your custom tasks in a row, then first 5 will enter their doInBackground(), the rest 10 will get into the queue, but for the 16th a new worker thread will be created so it'll start execution immediately. So in this case at most 6 tasks will run simultaneously.

There is a limit of how many tasks can be run simultaneously. Since AsyncTask uses a thread pool executor with limited max number of worker threads (128) and the delayed tasks queue has fixed size 10, if you try to execute more than 138 your custom tasks the app will crash with java.util.concurrent.RejectedExecutionException.

Starting from 3.0 the API allows to use your custom thread pool executor via AsyncTask.executeOnExecutor(Executor exec, Params... params) method. This allows, for instance, to configure the size of the delayed tasks queue if default 10 is not what you need.

As @Knossos mentions, there is an option to use AsyncTaskCompat.executeParallel(task, params); from support v.4 library to run tasks in parallel without bothering with API level. This method became deprecated in API level 26.0.0.

UPDATE: 3

Here is a simple test app to play with number of tasks, serial vs. parallel execution: https://github.com/vitkhudenko/test_asynctask

UPDATE: 4 (thanks @penkzhou for pointing this out)

Starting from Android 4.4 AsyncTask behaves differently from what was described in UPDATE: 2 section. There is a fix to prevent AsyncTask from creating too many threads.

Before Android 4.4 (API 19) AsyncTask had the following fields:

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);

In Android 4.4 (API 19) the above fields are changed to this:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);

This change increases the size of the queue to 128 items and reduces the maximum number of threads to the number of CPU cores * 2 + 1. Apps can still submit the same number of tasks.

aSync Task can't be executed twice

As the exception itself explains, you cannot execute an AsyncTask more than once, unless you create a new instance of it and call .execute.

For example:

async = new AsyncTask();
async.execute();

*in order to execute more than once, you need to re-create the instance (using new) the number of times you want to execute it.

Execute AsyncTask several times

AsyncTask instances can only be used one time.

Instead, just call your task like new MyAsyncTask().execute("");

From the AsyncTask API docs:

Threading rules

There are a few threading rules that must be followed for this class to work properly:

  • The task instance must be created on the UI thread.
  • execute(Params...) must be invoked on the UI thread.
  • Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
  • The task can be executed only once (an exception will be thrown if a second execution is attempted.)

Running same Asynctask multiple times sequentially

You could use a field variable in the outer class:

private int count;
private void attemptConnect(){
count = 0;

new MyTask().execute("");
}

class MyTask extends AsyncTask<String, String, String> {
@Override
protected String doInBackground(String... params) {
return null;
}

@Override
protected void onPostExecute(String s) {
count++;
if(count < 5){
new MyTask().execute("");
}
}
}

Or pass in a count to the AsyncTask constructor:

private void attemptConnect(){
new MyTask(0).execute("");
}

class MyTask extends AsyncTask<String, String, String> {
private int count;

public MyTask(int count){
this.count = count;
}

@Override
protected String doInBackground(String... params) {
return null;
}

@Override
protected void onPostExecute(String s) {
if(count < 4){
new MyTask(++count).execute("");
}
}
}

AsyncTask and error when executed twice

No. You cannot execute the same async task twice. You are able to do it again after 30 secs because the async task completes processing and returns the result from doInBackground(). Hence you need to create an object every time or use a progress dialog to block the user from clicking on the button again. Show the progress dialog in onPreExecute() and dismiss in onPostExecute().

How to make more than one Android AsyncTask run at the same time?

Use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) instead of execute(). Quoting the AsyncTask documentation:

If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.



Related Topics



Leave a reply



Submit