1

我有一个 android 应用程序,用 java 编写,它使用AsyncTask下载数据。需要AsyncTask来处理整个下载过程中显示的进度对话框

实际下载是通过单独的线程downloadAllUpdater启动的。虽然我知道这不是惯例,但需要一个线程,因为下载过程分布在 7 个类中,并且在下载过程中没有其他方法可以更新进度条,因为我无法从任何地方运行publishProgress调用其他类。

我的主要活动如下所示:

private Download downloadAll;

private int totalBlocksLeft;

private boolean downloadComplete;
private boolean downloadFailed;

private PerformTask currentPerformTask;

public void downloadAllClick(View view) //When the download all button is clicked
{
    currentPerformTask = new PerformTask();

    currentPerformTask.execute();
}

private class PerformTask extends AsyncTask<Void, Integer, Integer>
{
    protected void onPreExecute()
    {
        usingDialog = new ProgressDialog(WifiAudioActivity.this);

        usingDialog.show();
    }

    protected Integer doInBackground(Void... voi) 
    {
        downloadAll = new Download();

        downloadComplete = false;   //Assume the download is not complete

        downloadAllUpdater.start(); 

        downloadFailed = false;

        while ((downloadComplete == false) && (downloadFailed == false))   
        {
            blocksDownloaded = downloadAll.getTotalBlocksLeft();

            publishProgress(blocksDownloaded);
        }

        return 0;
    }

    protected void onProgressUpdate(Integer... progress) 
    {
        usingDialog.setProgress(progress[0]);
    }

    protected void onPostExecute(Integer result) 
    {
        usingDialog.dismiss();
    }
}

Thread downloadAllUpdater = new Thread()
{
    public void run() 
    {
        int runRetryCount = 0;

        while ((!(downloadComplete)) && (!(downloadFailed)))
        {
            downloadComplete = download.downloadAudio(totalBlocksLeft);  //Download the audio

            if (!(downloadComplete))
            {
                runRetryCount++;
            }

            if (runRetryCount > Consts.RETRY_TOTAL)
            {
                downloadFailed = true;
            }
        }
    }
};

单击按钮启动下载,该按钮启动downloadAllClick()方法。

第一次按下按钮时,这一切都很好。

但是,当第二次按下按钮时(第一次完成后),我收到一个错误并且程序强制关闭。

我很确定错误是因为我正在运行线程,downloadAllUpdater第二次,因为如果我有一个单独的方法,只是downloadAllUpdater.start(),它也会因同样的错误而崩溃。

任何人都可以帮忙吗?以下是错误日志:

08-23 11:22:34.954: W/dalvikvm(1485): threadid=14: thread exiting with uncaught exception (group=0x400259f8)

08-23 11:22:35.014: E/AndroidRuntime(1485): FATAL EXCEPTION: AsyncTask #5

08-23 11:22:35.014: E/AndroidRuntime(1485): java.lang.RuntimeException: An error occured while executing doInBackground()

08-23 11:22:35.014: E/AndroidRuntime(1485):     at android.os.AsyncTask$3.done(AsyncTask.java:200)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.lang.Thread.run(Thread.java:1102)

08-23 11:22:35.014: E/AndroidRuntime(1485): Caused by: java.lang.IllegalThreadStateException: Thread already started.

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.lang.Thread.start(Thread.java:1331)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at com.que.wifiaudio.WifiAudioActivity$PerformTask.doInBackground(WifiAudioActivity.java:518)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at com.que.wifiaudio.WifiAudioActivity$PerformTask.doInBackground(WifiAudioActivity.java:1)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at android.os.AsyncTask$2.call(AsyncTask.java:185)

08-23 11:22:35.014: E/AndroidRuntime(1485):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)

08-23 11:22:35.014: E/AndroidRuntime(1485):     ... 4 more
4

3 回答 3

2

你不能start一个线程两次。您可以downloadAllUpdater改为制作 Runnable:

Runnable downloadAllUpdater = new Runnable() { //rest unchanged

并将代码替换为doInBackground

new Thread(downloadAllUpdater).start();

这样,每次都会创建一个新线程,运行相同的任务。

但是doInBackground已经在后台线程上运行,您确定需要创建一个新线程吗?如果没有,只需运行 runnable:downloadAllUpdater.run();而不创建新线程。

于 2012-08-23T11:17:26.580 回答
1

不确定这是否与您看到的错误有关,但您当前的代码不是线程安全的。您当前正在从两个不同的线程(和downloadComplete)分配成员变量。这种用法会导致竞争条件和意外结果。请阅读Java 中的并发(即关键字),以同步您的线程。downloadFailedPerformTaskdownloadAllUpdatersynchronized

于 2012-08-23T19:27:37.293 回答
0
runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub

                        //do you download here

                    }
                });

在 Asyctask 中,您无法访问发生在不同主题中的内容

于 2012-08-23T11:17:27.147 回答