Android AsyncTask не остановится при отмене, почему? - PullRequest
16 голосов
/ 10 февраля 2011

У меня есть AsyncTask, который я закрыл в событии жизненного цикла onPause Activity, поэтому он не запускается, когда кто-то покидает приложение, но продолжает работать, несмотря на это. Я добавил несколько трассировок, и этот фрагмент показывает проблему.

    Trace.d(TAG,"Task state: " + myTask.getStatus() );
    myTask.cancel(true);
    Trace.d(TAG,"Task state: " + myTask.getStatus() );

Выходы:

Task state: RUNNING
Task state: RUNNING

Почему метод cancel () не влияет на состояние задачи? Я заметил, что в документах говорится, что метод отмены будет «пытаться» остановить задачу, но при каких обстоятельствах она не будет выполнена? Задача определенно выполняется, поскольку она выводит выходные данные журнала каждые десять секунд, и, как вы можете видеть выше, ее состояние возвращается как выполненное.

Обновление: я добавил трассировку, чтобы показать мне также состояние isCancelled (), и оно меняется. Поэтому вызов отмены (true) изменяет отмененное состояние с false на true, но, по-видимому, не влияет на состояние и не останавливает поток.

Ответы [ 5 ]

3 голосов
/ 15 июля 2011

Имейте в виду, что ваша активность и ваша AsyncTask являются двумя отдельными потоками. Так что даже если вы отмените AsyncTask, код для отмены задачи может еще не запуститься! Вот почему вы видите, что AsyncTask все еще работает даже после исправления вашей ошибки. Я не думаю, что статус изменится до тех пор, пока doInBackground() в вашей AsyncTask не завершится. (Поэтому убедитесь, что вы проверяете isCancelled() и возвращаетесь рано, когда вас отменили!)

2 голосов
/ 24 декабря 2013
thread.cancel(true);

Устанавливает только переменную в классе AsyncTask. Что вам нужно сделать, это внедрить цикл в фоновую задачу, если вы этого еще не сделали. Затем проверьте и разорвите цикл, если для каждой итерации установлено значение true.

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

    synchronized(this) {

        for(int i = 0; i < 9000; i++) {

            if(thread.isCancelled()) break;

            // do stuff

        }

    }

}

Тогда просто установите его на отмену всякий раз, когда вам нужно остановить его. Затем он остановится перед следующей итерацией.

@Override
public void onStop() {

    super.onStop();

    thread.cancel(true);

}

@Override
public void onDestroy() {

    super.onDestroy();

    thread.cancel(true);

}
2 голосов
/ 10 февраля 2011

Я копнул глубже и вспомнил, что мой поток вызывал довольно плохо написанный метод, содержащий это, создавая другой поток внутри того, который мне нужно отменить:

public static void haveASleep(int milliseconds)
{
    try
    {
        Thread.sleep(milliseconds);
    }
    catch (InterruptedException ie)
    {
        Trace.w(TAG,"Sleep interrupted");
    }
}

Так что происходило то, что поток AsyncTaskвызывает этот метод, чтобы подождать некоторое время, и во время сна в методе AsyncTask происходит вызов метода cancel (), что вызывает исключение в спящем потоке.Мой код бесполезно перехватил и поглотил это исключение, вместо того, чтобы использовать его для выключения AsyncTask.

Решение состояло в том, чтобы искать исключение во сне, и, если оно выбрасывается, тихо выходить из потока.Приложение теперь работает как положено, НО ...

Состояние сразу после вызова метода cancel () остается РАБОТАЮЩИМ, но я подозреваю, что это потому, что в тот момент оно все еще работает, а ОС еще незакрой это.Я понятия не имею, правда ли это, но это моя лучшая оценка.

0 голосов
/ 09 октября 2013

Еще одна возможная ошибка, чтобы проверить, сталкиваетесь ли вы с этой проблемой:

Убедитесь, что вы не запускаете две AsyncTasks.

0 голосов
/ 10 февраля 2011

Даже если вы знаете, как работает отмена, очень сложно определить, в каком состоянии ваш поток будет остановлен. Поэтому я предлагаю реализовать собственный безопасный способ остановки потока, чтобы вы были уверены, в каком состоянии вы останавливаетесь, и убедитесь, что нет утечек памяти и т. Д. Из более подробной информации о том, как остановить поток в java в безопасном режиме. способ проверить эту тему Как быстро и чисто прервать поток в Java?

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