2

I am dealing with quite a bit of legacy AsyncTask code and have to write some myself too in our codebase. But, the careful reading of the cancel() method from the docs has confused me quite a bit. The docs say:

Attempts to cancel execution of this task. This attempt will fail if the task has already completed, already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

Calling this method will result in onCancelled(Object) being invoked on the UI thread after doInBackground(Object[]) returns. Calling this method guarantees that onPostExecute(Object) is never invoked. After invoking this method, you should check the value returned by isCancelled() periodically from doInBackground(Object[]) to finish the task as early as possible.

So, there might be a scenario where the AsyncTask has finished and returned from doInBackground() but before calling onPostExecute(), the task was canceled through cancel() which resulted in a call to onPostExecute() anyway. This might be dangerous if the cancellation was initiated from onPause() of Activity.

Also, this question on SO supports the documented behavior of cancellation: onPostExecute on cancelled AsyncTask

So, should I start checking for if(isCanceled()) at the start of onPostExecute() from now on?

Manish Kumar Sharma
  • 12,982
  • 9
  • 58
  • 105
  • "So, there might be a scenario where the AsyncTask has finished and returned from doInBackground() but before calling onPostExecute(), the task was canceled through cancel() which resulted in a call to onPostExecute() anyway. This might be dangerous if the cancellation was initiated from onPause() of Activity." Did you encounter this case? – Programming Pirate Aug 30 '17 at 10:28
  • @ProgrammingPirate : This is a code in production for a business. How can I take risks when it is at least documented in the official docs? – Manish Kumar Sharma Aug 30 '17 at 10:30
  • @ProgrammingPirate :Also, since this is a multithreading scenario, catching the scenario might not be that easy. – Manish Kumar Sharma Aug 30 '17 at 10:31

1 Answers1

1

So, should I start checking for if(isCanceled()) at the start of onPostExecute() from now on?

Definetly not, it is already checked.

  private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

ref:AsyncTask.java

csenga
  • 3,819
  • 1
  • 21
  • 31
  • I actually saw the cancel() method and there is `mCancelled.set(true);`. How can you stop anyone from calling this method and setting this flag? And, when the flag has been set, isCancelled() returns true in onPostExecute() which means that at this moment, someone truly wants the task gone. – Manish Kumar Sharma Aug 30 '17 at 11:07
  • 1
    In other words, after finish() method picks onPostExecute(), cancel() gets called and flag is set. There is definitely the chance that in onPostExecute(), isCancelled() returns true. Is it not? – Manish Kumar Sharma Aug 30 '17 at 11:08
  • In the case you would need another thread to interact with the asynctask. Asynctask is designed to be called only from the UI thread. From the doc: "AsyncTask enables proper and easy use of the UI thread. This class allows you to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers....An asynchronous task is defined by a computation that runs on a background thread and whose result is published on the UI thread." – csenga Aug 30 '17 at 11:29
  • Also check "Threading rules" The AsyncTask class must be loaded on the UI thread. The task instance must be created on the UI thread. execute(Params...) must be invoked on the UI thread. ref: https://developer.android.com/reference/android/os/AsyncTask.html – csenga Aug 30 '17 at 11:31
  • So if you use Asynctask from the ui thread there will be no problem with the cancelled flag. – csenga Aug 30 '17 at 11:33