2013-07-24 38 views
0

我在Android项目中遇到了一个涉及aSyncTasks的问题,在一些研究发现答案后,我没有发现任何人曾经说过的话,所以我想我会与SO分享如果任何人发现它有任何用处,可以通过社区。aSyncTask死锁第二个aSyncTask

我的问题的简要概述:

我有一个UI活动类被点击安装按钮,当下载多个文件包。 “捆绑”文件最多分为四个独立下载,“组”信息与其他文件信息一起存储在自定义类中。当单击下载按钮时,(最多)四个作业通过一个实用程序DownloadUtilities与Android DownloadManager排队。

当DownloadUtilities对“组”下载进行排队时,DownloadManager下载引用存储在“组”自定义类的内部供以后使用。

Download Utilities类使用BroadcastReceiver来确认文件,并在下载完成后显示它们已完成时,将组的每个元素的下载引用更新为0。

一旦组中的所有文件都完成下载,就可以对其进行处理。这是由DownloadReceiver触发的aSyncTask完成的。

这反过来会触发广播以通知UI活动所请求的下载已完成,因此可以相应地更新UI。

一切直到此时伟大的工作,但是,我发现了一个问题,当我尝试添加一个进度条来显示“本集团”

要更新进度的进度,我创建了一个新的AsyncTask可能查询下载管理器计算下载文件的总大小,然后每秒轮询一次以更新ProgressBar以显示当前的下载进度。

的doInBackground()线程由以下伪代码:

Check if file1 is being downloaded, if it is, query the download manager for the total file size and add it to total 
Same for files2-4 

While the download references are not all 0: 
If file 1 is still downloading, get file1 download total 
Same for file2-4 
Update progress to sum of downloaded bytes/total 

我发现的问题是,该系统将发生死锁。 Logcat会告诉下载接收器被告知文件已经由DownloadManager完成下载,并且ProcessDownload aSyncTask onPreExecute()正在运行,但doInBackGround从未运行。

与此同时,下载监视器不停地在doInBackground()中循环,因为while循环的条件永远不会被取消断言,因为deassertion是在ProcessDownload doInBackground()线程中完成的。

很明显,aSyncTask doInBackground()方法是相互排斥的,所以导致死锁,但我不知道为什么。我从来没有故意以这样的方式构建我的代码,在过去,这提出了一个问题...

我的理解是,aSyncTasks提供了一种开发人员友好的方式来多线程代码,但似乎并非如此。 ..

回答

1

因此,我花了几个小时试图找出可能导致问题的原因,并得出结论,根据我对什么是同步任务的了解,没有理由我的代码不应该工作...于是我上网浏览文档,最终找到了答案。

“Honeycomb的开始,任务是在单个线程执行造成

并行执行。 避免常见的应用错误。如果你真正想要的并行执行,你可以调用 executeOnExecutor(java.util中。 concurrent.Executor,Object []) WITHTHREAD_POOL_EXECUTOR。“

看来我的思想确实被用来作为Honeycomb的方式,它已经不再是这样了。 aSyncTasks从UI线程卸载代码,然而,它将它卸载到单个线程上,并且顺序执行多个aSyncTask doInBackground()方法。

所以我回去改变了我的代码,以使用好的'Java Java线程'和'瞧,我的代码工作!

任何人都想使用相关的代码,这是值得仔细思考和寻找一个SyncTasks,以确保你了解它的行为。他们是我过去使用过的很棒的工具,但是更多的“先进”?东西,回到基础可能会更好。

希望这将是使用的人,我已经浪费了很多时间在这,因为的AsyncTask -.-

Source that gave me the answer

编辑行为的一个简单的误解:

道具Krylez指向我http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html其中还具有保持与蜂窝设备之前和之后的兼容性真正雄辩的方式。所有这一切需要的是修改的AsyncTask调用

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) { 
    myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} 
else { 
    myTask.execute(); 
} 

而归还蜂窝+行为,它是如何使用的是

+1

@CommonsWare与片段处理的兼容性没有在时间的变化的一个很好的解释,沿。 http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html – Krylez

+0

该页面也将节省我更多的时间!如果有人在同一条船上磕磕绊绊,请将其添加到我的答案中 – o0rebelious0o