简体   繁体   中英

Why is my Service's AsyncTask blocking AsyncTasks from the main Activity?

I'm trying to write a simple Service that will do something every few seconds. But when I run the Service while trying to run other AsyncTasks in the main Activity, I noticed that the other AsyncTasks get stuck at onPreExecute. When I disabled the service, everything worked as expected. Is there a reason why the Service's AsynTask is blocking the other AsyncTasks?

Service

public class SVC_SyncData extends Service {

    private final String TAG = "SVC_SyncData";

    private AT_SyncData m_SyncPoll = null;

    public static boolean isRunning = false;

    public SVC_SyncData() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "onCreate");
        m_SyncPoll = new AT_SyncData(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand");
        m_SyncPoll.execute();
        isRunning = true;
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy");
        m_SyncPoll.cancel(false);
        isRunning = false;
    }
}

AT_SyncData's doInBackground

@Override
protected Void doInBackground(Void... params) {
    Log.i(TAG, "doInBackground");

    try {
        while (!isCancelled()) {
            Log.i(TAG, "syncData");

            // Sleep until next cycle
            Thread.sleep(5000);
        }
    }
    catch (Exception ex) {
        ex.printStackTrace();
    }

    return null;
}

The AsyncTask documentation states:

Order of execution

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. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

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

Thus, newer versions of android will have this problem you describe. You need to use executeOnExecutor to make sure that you are running on separate threads.

Furthermore, if you have service that you want to run in a separate thread I recommend either:

  1. Use an IntentService
  2. Sometimes you will want more control over your service's lifecycle than what IntentService gives you, in those cases you can just create a thread in the service and run your background code in that. Actually, to be more specific, create a HandlerThread which includes a Looper so you can use the standard android method for communication (messages) between your main thread and the background thread. Personally, I usually choose this option for my services.

If its in a service just use a Thread or Callable. AsyncTask is for UI threads. A service is not a UI thread.

Here's what the API says: "AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time , it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask"

AsyncTask

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM