2011-08-10 40 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()中,你从这个列表中删除它,它会修改它并导致异常。