Использование mayInterruptIfRunning для отмены ASyncTask - Порядок вызова функции - - PullRequest
4 голосов
/ 20 декабря 2011

Когда я вызываю cancel(false), чтобы остановить мой ASyncTask, я обнаруживаю, что функция onCancelled() вызывается еще до того, как я смог обнаружить, что задача отменяется в doInBackground() с использованием isCancelled().

Я пытался изменить аргумент функции отмены на true, но это тоже не помогло.

Когда я прочитал документацию, я понял, что смогу обнаружить отмену в doInBackground(), вернитесь из этой функции и только после того, как вместо onPostExecute().

* 1014 будет вызвана функция onCancelled(). Я что-то упустил?Нужно ли добавлять дополнительные механизмы синхронизации, чтобы все происходило в том порядке, в котором я ожидаю?

РЕДАКТИРОВАТЬ:

Вот как организован код:

    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();
        }
    }

Таким образом, проблема заключается в том, что в настоящий момент все еще выполняются некоторые операции с базой данных, даже если она удаляется в onCancelled().Симптом заключается в том, что порядок сообщений «вылезает» и «отменяется!»не согласуется (и я сделал это также с отладчиком, похоже, что вызов cancel() переходит непосредственно к onCancelled(), пока другой поток все еще работает.

Одной из возможных причин может быть этосообщение Я только что нашел ...? (я запускаю это на Froyo)

БОЛЬШЕ ...

Хотя я установил флаг в вызове cancel() как ложный, яобнаружите, что функция doInBackground() не имеет возможности завершить или обнаружить отмену (она даже не доходит до оператора return)

Ответы [ 2 ]

4 голосов
/ 06 января 2012

Итак, пару вещей я узнал (и, думаю, я понимаю, что происходит) ...

Я думал, что функция onCancelled будет вызываться вместо onPostExecute после возврата doInBackground ... вместо этого onCancelled вызывается в момент вызова функции AyncTask.cancel ().

Итак, у меня была проблема с тем кодом, который у меня был, который закрывал и удалял базу данных, над которой работал поток doInBackground. Так что большую часть времени этот поток просто зависал (не видел много в logcat, но большую часть времени он попадал на проверку if (isCancelled()) ...

Только что изменил организацию этого задания, и теперь оно работает нормально. Создайте отдельную функцию для очистки, которая будет вызываться doInBackground, когда isCancelled возвращает true. Не использовал onCancelled ни для чего ...

0 голосов
/ 20 декабря 2011

Вы сможете обнаружить отмену в doInBackground(), только если вы кодируете ее таким образом. Это «обнаружение» происходит не с помощью асинхронного обратного вызова. Другими словами, doInBackground() должен периодически проверять состояние отмены и обрабатывать случай, когда было запрошено отмену. Можете ли вы опубликовать фрагмент вашего doInBackground()?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...