2011-08-10 23 views
1

私は、その実行中に、AsyncTaskのカップルとThreadのカップルをキックオフするアクティビティを持っています。Android - スレッドを追跡する

これらの活動が破壊された時/再作成、その後のエラーのすべての種類は、私ができることを意味ArrayList<Thread>()ArrayList<AsyncTask>()に自分自身を追加するので、私の明るいアイデアは、各非UIスレッドが自身を登録することだった起こり続ける場合は、onDestroy()、これらのArrayListを反復処理し、そのようにそれらを破壊する:

@Override 
public void onDestroy() 
{ 
    for(AsyncTask task : tasks) 
     task.cancel(true);* 

    for(Thread thread : threads) 
     thread.interrupt(); 
} 

は、残念ながら、これは*でマークされた行にjava.util.ConcurrentModificationExceptionをスローします。私はそれぞれのforループをsynchronizeブロックにラップして、ArrayListが他のどのThreadによっても変更されていないことを確認しました。

Do AsyncTask s完了時に自分自身を破壊します(したがって、上記のエラーが発生します)。

誰かがAndroid環境でスレッドを制御するより良い方法を知っていますか? for(int i =0 : i < array.size() ; i++)を使用するようにコードを変更する

EDIT

は、この問題を解決するようだが、私はまだ/それがなぜ起こるか/知っていただきたいと思います:、

synchronized(tasks) 
    { 
     for(int i=0; i < tasks.size(); i++) 
      tasks.get(i).cancel(true); 
    } 

    synchronized(threads) 
    { 
     for(int i=0; i < threads.size(); i++) 
      threads.get(i).interrupt(); 
    } 

答えて

1

私の知る限りAsyncTasksをonPostExecuteを実行してインスタンスをnullなどに設定した後は消えます。 ServiceまたはAsyncTaskで実行できなかったスレッドで何をしていますか?アプリがフォアグラウンドにないときにこれらのスレッドにエラーを発生させるスレッド(UIの動作、runOnUIThreadなど)でUI操作を行っていますか?

サービスでの作業についての素晴らしいことは、あなたがアプリを終了しようとしていることをブロードキャストして、もはや実行する必要のないサービス内のアクションを停止することです。アプリがフォアグラウンドに入ったときにもう一度やり直してください。

+0

私はセマフォなどでJavaスレッドと密接に通信するネイティブメソッドを実行しています。 – Graeme

+0

そして、もはや走っていないときにdestroy()を呼び出すのと同じように「消えますか? – Graeme

1

すべての変更が​​で囲まれていない限り、並行変更を防止しません。ここでやっているだけでは不十分です。 doInBackgroundが終了するとAsyncTaskは確かに自分自身を殺すん

// create the empty list 
List tasks = Collections.synchronized(new ArrayList<AsyncTask>()); 
+0

申し訳ありませんが、私は言及すべきです、私はまた、配列が使用される(すなわち、追加される)コード内の他の場所を同期させました。 – Graeme

0

は、同期のコレクションを使用してみてください。その点については、Javaスレッドはrun()が終了したときと同じことを行います。 cancel()を呼び出すと、asyncTaskをキャンセルできるかどうかによってtrueまたはfalseが返されます。

スレッドで使用されているものを変更しようとすると、ConcurrentModificationExceptionがスローされます。私が理解しているところでは、配列リストはUIスレッドでasynctasksを取り消すために使用されており、両方のasynctasksで自身を登録するために使用されています。私はあなたが配列リストのコレクションを同期させていないどこかを推測しています。おそらく、

synchronized(tasks){ 
    for(int i=0; i < tasks.size(); i++){ 
     tasks.get(i).cancel(true); 
    } 
} 

はそれを修正します。すべてのasyncTaskでタスクも同期されていることを確認してください。または、それを揮発性にすることができます。

しかし、あなたがonDestroyにいるときには、asyncTasksはおそらく既に完了しているはずです(またはそうしなければならない)ので、キャンセルされたことを確認する必要があるのはわかりません。ユーザーがアプリを離れるときにそれらを実行したくない場合は、onPause()に配置する必要があります。

+0

アクティビティが残っているとき - アプリケーションではありません。 私の編集と同様に、forループの風味はこの問題の影響を受けませんので、他のタイプのforループを取り巻く方法論であると仮定します( 'Iterator'を使用することもあります)。 また、私はあなたを混乱させるかもしれないと思います。私が「破壊する」と言うとき、私が意味することを殺すことを意味するわけではありません。スレッドは、実行終了時にこれを行いません。 – Graeme

3

これは非常に古いスレッドですが、これは一般的な問題であるため、とにかく答えていきます。ここで何が起こっている

for(AsyncTask task : tasks) 
    task.cancel(true);` 

はそれを反復されながらそのまま滞在するtasksオブジェクトを必要とするため、各ループを使用して、次のコードということです。私の推測では、あなたの仕事のonPostExecute()では、それを修正して例外を引き起こすこのリストから削除しています。

関連する問題