2011-08-10 67 views
1

我有一個活動,在執行過程中,它啓動了AsyncTask秒和幾個Thread s。Android - 跟蹤主題

如果這些繼續當活動被銷燬/重建則錯誤的種種會發生,所以我的好主意是讓每一個非UI線程自身進行註冊,將自身添加到ArrayList<Thread>()ArrayList<AsyncTask>()這意味着我可以,的onDestroy()通過這些迭代的ArrayList並摧毀他們,像這樣:

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

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

不幸的是,這將引發上標有*的線java.util.ConcurrentModificationException。我試圖在synchronize塊中包裝每個for循環以確保ArrayList不被其他Thread修改。

AsyncTask完成後自毀(因此拋出上面的錯誤)?

有誰知道在Android環境中控制線程的更好方法嗎?

編輯

更改爲使用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或類似的東西。你在一個線程中做什麼,你不能在一個Service或AsyncTask中做什麼?你是否正在線程中執行UI操作(如runOnUIThread或其他什麼東西),當應用程序不在前臺時會導致這些線程出錯?

在服務中做事情的好處是,您可以廣播您即將關閉應用程序,並停止服務中您不再需要運行的任何操作,基本上使服務休眠,直到您啓動服務當應用程序進入前景時再次。

+0

我正在運行本地方法,通過信號燈等與Java線程進行密切通信。 – Graeme

+0

然後,「消失」,因爲他們在不再跑步時稱自己爲摧毀()。 – Graeme

1

你不阻止併發修改,除非在應用程序中的所有修改是由​​包圍;僅僅在這裏做是不夠的。

嘗試使用同步的集合:

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

對不起,我應該提到,我還在代碼中使用數組的代碼中同步了另一個地方(即添加到)。 – Graeme

0

的AsyncTask確實殺死自己當doInBackground完成。對於這個問題,java線程在run()完成時做同樣的事情。根據是否可以取消asyncTask,對cancel()的調用只返回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對象,而它是通過它迭代維持不墜一個for-each循環。我的猜測是在你的任務的onPostExecute()中,你從這個列表中刪除它,它會修改它並導致異常。