Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Usage of mayInterruptIfRunning to cancel ASyncTask - Function call order -

When I call cancel(false) to stop my ASyncTask, I find that the onCancelled() function is called even before I was able to detect the task is being cancelled in doInBackground() using isCancelled().

I tried to change the argument of the cancel function to true, but that did not help either.

When I read the documentation, my understanding was that I would be able to detect the cancellation in doInBackground(), return from that function and only after the onCancelled() function would be called in place of the onPostExecute().

Am I missing something ? Do I need to add more synchronization mechanisms to make sure things happen in the order I expect to ?

EDIT:

Here is the way the code is organized:

    AsyncTask<Void,Integer,Void>() {
        ProgressDialog mProgressDialog;

        @Override
        protected Void doInBackground(Void... voids) {

                for (int i=0; i<size; i++) {
                    publishProgress(i/100);
                    if (isCancelled()) {
                        Log.d(TAG, "getting out");
                        return null;
                    }
                    // do some database operations here
                }

                // do some house cleaning work also here
            }
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // create the progress dialog if needed
            mProgressDialog = new ProgressDialog(context);
            mProgressDialog.setMessage("Do it!");
            mProgressDialog.setIndeterminate(false);
            mProgressDialog.setMax(100);
            mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                public void onCancel(DialogInterface dialogInterface) {
                    cancel(false);
                }
            });
            mProgressDialog.setCancelable(true);
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.show();

            // create some database here
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            mProgressDialog.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            mProgressDialog.dismiss();
        }

        @Override
        protected void onCancelled() {
            super.onCancelled();
            Log.d(TAG, "Cancelling !");

            // since we are cancelling the operation, close and delete the database that was being created
            mProgressDialog.dismiss();
        }
    }

So the problem is that right now, there are still some operations being performed on the database even though it is being deleted in onCancelled(). The symptom is that the order of the message "getting out" and "Cancelling !" is not consistent (and I did it also with the debugger, seems like the cancel() call goes directly to the onCancelled() while the other thread is still running.

One possible reason may be this message I just found... ? (I am running this on Froyo)

MORE...

Although I set the flag in the cancel() call to false, I find that the doInBackground() function does not have a chance to finish or detect the cancellation (it even never gets to a return statement)

like image 790
Matthieu Avatar asked Oct 09 '22 04:10

Matthieu


1 Answers

So a couple of things I found out (and I think I understand what was happening)...

I thought the onCancelled function would be called instead of the onPostExecute after the doInBackground returned... instead, onCancelled is called right at the time the AyncTask.cancel() function is called.

So the problem I had is that with the code I had, that would close and delete the database the doInBackground thread was working on. So most of the time, that thread would just crash (did not see much in the logcat, but most of the time, it would get to the check if (isCancelled()) ...

Just changed the organization of this task and it is working fine now. Create a separate function to do the clean-up that would be called by the doInBackground when isCancelled returns true. Did not use onCancelled for anything...

like image 132
Matthieu Avatar answered Oct 13 '22 12:10

Matthieu