1

AsyncTaskを使用してデータをダウンロードするJavaで記述されたAndroidアプリがあります。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()メソッドが開始されます。

これはすべて、ボタンが最初に押されたときに正常に機能します。

ただし、ボタンを2回押すと(1回目の完了後)、エラーが発生し、プログラムが強制終了します。

スレッド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スレッドを2回実行することはできません。downloadAllUpdater代わりにRunnableを作成できます。

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

そして、コードを次のように置き換えますdoInBackground

new Thread(downloadAllUpdater).start();

このようにして、同じタスクを実行するたびに新しいスレッドが作成されます。

ただしdoInBackground、すでにバックグラウンドスレッドで実行されていますが、新しいスレッドを作成する必要がありますか?downloadAllUpdater.run();そうでない場合は、新しいスレッドを作成せずに、runnableを実行します。

于 2012-08-23T11:17:26.580 に答える
1

これが表示されているエラーに関連しているかどうかはわかりませんが、現在のコードはスレッドセーフではありません。現在、メンバー変数downloadCompletedownloadFailed2つの異なるスレッド(PerformTaskおよびdownloadAllUpdater)から割り当てています。この使用法は、競合状態と予期しない結果につながります。スレッドを同期するために、Javaでの並行性(つまり、synchronizedキーワード)について読んでください。

于 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 に答える