2011-02-10 12 views
16

ActivityのonPauseライフサイクルイベントでシャットダウンしたAsyncTaskがあるので、誰かがアプリケーションを離れるときに実行されませんが、これにもかかわらず続行されます。トレースを追加しました。このスニペットは問題を示しています。Android AsyncTaskはキャンセルされても停止しません。なぜですか?

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

出力:

Task state: RUNNING 
Task state: RUNNING 

なぜキャンセル()メソッドは、タスクの状態に影響を持っていないですか?私はドキュメントをキャンセルメソッドがタスクを停止しようとしますが、どのような状況で失敗すると言うことに気づいた? 10秒ごとにログ出力を出力しているので、タスクは確実に実行されています。上記のように、ステータスは実行中として返されます。

更新:私はisCancelled()状態も表示するためにトレースを追加しましたが、それは変更されます。 cancel(true)を呼び出すと、キャンセルされた状態がfalseからtrueに変更されますが、明らかにStatusに影響を与えないか、スレッドを停止します。

+0

タスク内のループがタスクがキャンセルされたかどうかをチェックし、ループを終了する方法はありますか? –

+0

キャンセルの戻り値は何ですか?キャンセルしたと伝えましたか? –

+0

@Joelはい、私はそれを行うことができますが、他の場所でcancel()メソッドを使用するとき、私はそれが期待したことをしていない理由を理解したいと思います –

答えて

2

をチェックし、私は深く掘って、私のスレッドがこれを含むかなりひどく書かれたメソッドを呼び出したことを思い出し、私はキャンセルする必要がある1つの内部に別のスレッドを生成:

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

だから何が起こっていたましたAsyncTaskスレッドがこのメソッドを呼び出してしばらく待機し、スリープ中にAsyncTaskでcancel()メソッド呼び出しが発生すると、スレッドスリープで例外が発生します。私のコードは、AsyncTaskをシャットダウンするのではなく、その例外を捕まえて吸収しました。

解決策は、スリープ時に例外を探し、スローされた場合はスレッドを静かに終了させることでした。アプリケーションは現在期待どおりに動作しますが...

キャンセル()メソッド呼び出しの直後のステータスはRUNNINGのままですが、その時点でまだ実行中で、OSがまだシャットダウンしていないためですダウン。それが本当かどうかはわかりませんが、それは私の最善の見積もりです。

0

キャンセルの仕組みが分かっていても、スレッドが停止する状態を判断することは非常に難しいです。だから私はあなたのスレッドを停止するためにあなた自身の安全な方法を実装することをお勧めしますので、あなたは停止していることを確認し、メモリリークなどがないことを確認します。道このスレッドにHow to abort a thread in a fast and clean way in java?

+0

私は、JavaスレッドのAndroidラッパーであるAsyncTaskを使用しています少なくとも理論的には、スレッドの開始、管理、および停止を簡単に行うことができます。現時点では、スレッドを強制終了する必要があると思われますが、なぜキャンセル()メソッドが設計されたように表示されていないのかを理解したいと思います。 –

+0

AsyncTaskは単なるAndroidラッパーではありません。 Javaスレッドに対する主な利点は、UIスレッドで実行されるメソッドを使用して、GUIスレッドから簡単に更新できることです。だからAsyncTaskはJavaスレッドとして停止するのと同じ問題があります。 –

3

アクティビティとAsyncTaskは2つのスレッドに分かれています。したがって、AsyncTaskをキャンセルしても、タスクをキャンセルするコードがまだ実行されていない可能性があります。そのため、バグ修正後もAsyncTaskが実行されているのが見えてきます。私はあなたのAsyncTaskのdoInBackground()が完了するまで状態が変わるとは思わない。 (ですから、isCancelled()をチェックし、あなたがキャンセルされてきたとき、早期帰国していることを確認してください!)

0

あなたはこの問題に実行しているかどうかを確認するために別の可能な落とし穴:

は、2つのAsyncTasksを開始していないことを確認してください。

2
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); 

} 
+0

「スレッド」とは何ですか? –

関連する問題