2011-08-10 3 views
1

나는 실행 중에 액서스가 AsyncTask이고 어떤 것은 Thread이다.안드로이드 - 쓰레드 추적하기

이 계속되면 활동이 파괴 될 때/오류 모든 종류의 내가 할 수있는 것을 의미 ArrayList<Thread>()ArrayList<AsyncTask>()에 자신을 추가하고 있으니, 내 밝은 아이디어가 아닌 각 UI 스레드가 자신을 등록하는 것이었다 발생 후 다시,들의 OnDestroy() 이 ArrayLists를 통해 반복하고 그래서 같이 그들을 파괴 :

@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 do 완료시 자체 파괴 (따라서 위의 오류가 발생 함)?

안드로이드 환경에서 스레드를 제어하는 ​​더 좋은 방법을 아는 사람이 있습니까? for(int i =0 : i < array.size() ; i++)를 사용하는 코드를 변경

편집

이 문제를 해결하기 위해 보이지만 난 여전히/그런 일이 왜/알고 싶다 :

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로 설정했거나 사라지면 사라집니다. 서비스 또는 AsyncTask에서 수행 할 수없는 스레드에서 무엇을하고 있습니까? 응용 프로그램이 포 그라운드에 있지 않을 때 이러한 스레드가 오류를 발생시키는 스레드 (예 : runOnUIThread 또는 기타)에서 UI 작업을 수행하고 있습니까?

서비스에서 일하는 것에 대한 좋은 점은 앱을 닫으려는 방송을 할 수 있으며 더 이상 실행하지 않아도되는 서비스의 모든 동작을 중지 할 수 있으며 서비스를 실행하기 전까지 본질적으로 서비스를 휴면합니다. 앱이 포 그라운드로 들어 오면 다시 올라와야합니다.

+0

나는 세마포어 등을 통해 자바 쓰레드와 밀접하게 통신하는 네이티브 메소드를 실행 중이다. – Graeme

+0

그리고 더 이상 실행되지 않을 때 destroy()를 호출 할 때 "사라집니다"? – Graeme

1

모두 수정 사항이 synchronized으로 둘러싸여 있지 않으면 동시 수정을 막지 않습니다. 여기에서하는 것만으로는 충분하지 않습니다. 동기화 된 컬렉션을 사용

시도 : doInBackground가 완료되면

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

미안하지만, 나는 언급 했어야했다, 나는 또한 배열이 사용되는 (즉,에 추가되는) 코드에서 다른 장소를 동기화했다. – Graeme

0

AsyncTask를 실제로 자신을 죽일 않습니다. 자바 스레드는 run()이 끝나면 똑같은 동작을한다. cancel()을 호출하면 asyncTask를 취소 할 수 있는지 여부에 따라 true 또는 false 만 반환됩니다.

스레드에서 사용중인 내용을 수정하려고하면 ConcurrentModificationException이 발생합니다. 알다시피, 배열 목록은 UI 스레드에서 asynctasks를 취소하는 데 사용되고 있으며 asynctasks에서 자체적으로 등록하는 데 사용됩니다. 배열 목록 컬렉션을 동기화하지 않은 어딘가에서 추측하고 있습니다. 아마도

:

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

가 해결됩니다. 모든 asyncTasks에서 작업이 동기화되었는지 확인하십시오. 또는 휘발성으로 만들 수 있습니다.

아무리 빨리 당신이 onDestroy에있을 때 당신은 asyncTasks가 이미 완료되었거나 있어야합니다. 그래서 취소 된 이유를 알 필요가 없습니다. . 사용자가 앱을 나갈 때 앱을 실행하지 않으려면 onPause()에 넣어야합니다.

+0

활동이 남아있을 때 - 앱이 아닙니다. 내 편집에서와 마찬가지로 for 루프의 맛은이 문제의 영향을받지 않으므로 다른 for 루프를 사용하는 방법론이라고 가정합니다 (Iterator를 사용하는 것 같습니다). 또한 나는 내가 당신을 혼란스럽게했을지도 모른다라고 말합니다. 제가'파괴하다 '라고 말하면, 제가 의미하는 것을 죽이는 것은 쓰레기 수거에 대한 표시임을 의미하지는 않습니다. 쓰레드는 실행을 마칠 때 이것을하지 않습니다. – Graeme

3

이것은 매우 오래된 스레드이지만, 사람들이 자주 접하는 문제이므로 어쨌든 대답하겠습니다.

은 여기에서 일어나고있는 것은 다음과 같은 코드

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

가 그것을 통해 반복하는 동안 그대로 유지하는 tasks 객체를 필요로를위한 각 루프를 사용한다는 것입니다. 내 생각 엔 작업의 onPostExecute()에서이 목록에서이 목록을 제거하면 해당 목록이 수정되어 예외가 발생합니다.