Android AsyncTask no se detendrá cuando se cancela, ¿por qué?

Tengo un AsyncTask que cierro en el evento de ciclo de vida de OnPause de la actividad, por lo que no se ejecuta cuando alguien deja la aplicación, pero continúa a pesar de esto. He añadido algún rastreo y este fragmento muestra el problema.

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

Salidas:

 Task state: RUNNING Task state: RUNNING 

¿Por qué el método cancel () no tiene ningún efecto en el estado de la tarea? Observo que los docs dicen que el método de cancelación "intentará" detener la tarea, pero bajo qué circunstancias fallará? La tarea se está ejecutando definitivamente, ya que es salida salida de registro cada diez segundos, y como se puede ver por encima de su estado se devuelve como ejecución.

Actualización: agregé el rastreo para mostrarme el estado isCancelled () también y que cambia. Así que la llamada a cancelar (true) está cambiando el estado cancelado de falso a verdadero, pero aparentemente no tiene ningún efecto en el estado, o detener el hilo.

Tenga en cuenta que su Actividad y su AsyncTask son dos subprocesos separados. Así que incluso si cancela el AsyncTask, el código para cancelar la tarea no se puede ejecutar todavía! Es por eso que está viendo el AsyncTask todavía funcionando incluso después de corregir su error. No creo que el estado cambie hasta que doInBackground() en su AsyncTask se haya completado. (Así que asegúrese de que está revisando isCancelled() y volver temprano cuando se ha cancelado!)

Hice más profundo y recordé que mi hilo estaba llamando a un método bastante mal escrito que contenía esto, produciendo otro hilo dentro del que necesito cancelar:

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

Así que lo que estaba sucediendo era que el hilo de AsyncTask llama a este método para esperar un rato, y durante el sueño la llamada del método de cancel () ocurre en el AsyncTask, que causa una excepción en el sueño del hilo. Mi código unhelpfully capturado y absorbido que la excepción, en lugar de usarlo para apagar el AsyncTask.

La solución era buscar una excepción en el sueño, y si se lanza, para salir en silencio el hilo. La aplicación funciona ahora como se esperaba, PERO …

El estado inmediatamente después de la llamada al método cancel () sigue siendo RUNNING, pero sospecho que esto es porque en ese momento todavía está en ejecución, y el sistema operativo aún no lo ha cerrado. No tengo ni idea de si eso es cierto, pero esa es mi mejor estimación.

 thread.cancel(true); 

Sólo establece una variable en la clase AsyncTask. Lo que debe hacer es implementar un bucle en su tarea de fondo si no lo ha hecho ya. A continuación, compruebe y rompa el bucle si cancelar es cierto para cada iteración.

 @Override protected Void doInBackground(Void... params) { synchronized(this) { for(int i = 0; i < 9000; i++) { if(thread.isCancelled()) break; // do stuff } } } 

A continuación, sólo tiene que cancelar siempre que lo necesite para detener. A continuación, se detendrá antes de la siguiente iteración.

 @Override public void onStop() { super.onStop(); thread.cancel(true); } @Override public void onDestroy() { super.onDestroy(); thread.cancel(true); } 

Incluso si sabe cómo funciona cancelar es muy difícil determinar en qué estado se detendrá su hilo. Por lo tanto, sugiero implementar su propia forma segura de detener el hilo, por lo que estará seguro en qué estado se está deteniendo y asegúrese de que no hay fugas de memoria, etc De más información cómo detener un hilo en java en caja fuerte Manera de comprobar este hilo ¿Cómo abortar un hilo de una manera rápida y limpia en java?

Otro error posible para comprobar si se está ejecutando en este problema:

Asegúrese de no iniciar dos AsyncTasks.

  • Problemas al llamar a AsyncTask de IntentService
  • Android: problemas con una cadena de actividad multinivel
  • Cambiar la orientación de la orientación con AsyncTask
  • Cómo hacer que el hilo principal esperar, cuando no sé cuándo Async tarea terminar el trabajo.?
  • ¿Están encadenando AsyncTasks consideradas malas prácticas?
  • La clase interna puede acceder pero no actualizar los valores - AsyncTask
  • Bloqueo de registro de GCM AsyncTask hasta que se produzca el tiempo de espera
  • ¿Qué significan los tres puntos en "doInBackground (URL ... urls)"?
  • Manejo de errores Asynctask
  • ¿Cómo puedo coordinar dos tareas de fondo?
  • ¿Hay una manera de detener la ejecución de un HttpClient en un AsyncTask?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.