AsyncTask和Thread在java / android应用程序中不会运行两次

时间:2012-08-23 11:10:08

标签: java android multithreading android-asynctask

我有一个用java编写的Android应用程序,它使用 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()方法。

第一次按下按钮时,一切正常。

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

我很确定错误是因为我第二次运行Thread, 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

3 个答案:

答案 0 :(得分:2)

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

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

并将doInBackground中的代码替换为:

new Thread(downloadAllUpdater).start();

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

runOnUiThread(new Runnable() {

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

                        //do you download here

                    }
                });
在异步任务中

你无法访问在不同线程中发生的事情