Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
异步任务和线程赢得';t在java/android应用程序中运行两次_Java_Android_Multithreading_Android Asynctask - Fatal编程技术网

异步任务和线程赢得';t在java/android应用程序中运行两次

异步任务和线程赢得';t在java/android应用程序中运行两次,java,android,multithreading,android-asynctask,Java,Android,Multithreading,Android Asynctask,我有一个android应用程序,用java编写,它使用AsyncTask下载数据。异步任务用于处理整个下载过程中显示的进度对话框 实际下载是通过一个单独的线程启动的,DownloadAllUpdate。虽然我知道这不是惯例,但需要一个线程,因为下载过程分布在7个类中,并且在下载过程中没有其他方法更新进度条,因为我无法运行来自任何其他类的publishProgress调用 我的主要活动如下: private Download downloadAll; private int totalBlock

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

实际下载是通过一个单独的线程启动的,DownloadAllUpdate。虽然我知道这不是惯例,但需要一个线程,因为下载过程分布在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;
            }
        }
    }
};

一个线程不能启动两次。您可以将
downloadAllUpdater
改为可运行:

Runnable downloadAllUpdater = new Runnable() { //rest unchanged
并将
doInBackground
中的代码替换为:

new Thread(downloadAllUpdater).start();
这样,每次都会创建一个新线程,运行相同的任务

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

runOnUiThread(new Runnable() {

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

                        //do you download here

                    }
                });

在Asyctask中,您无法访问在不同线程中发生的内容,不确定这是否与您看到的错误有关,但您当前的代码不是线程安全的。您当前正在从两个不同的线程(
PerformTask
DownloadAllUpdate
)分配成员变量
downloadComplete
DownloadAllUpdate
)。这种用法将导致竞争条件和意外结果。请阅读有关同步线程的信息(即
synchronized
关键字)。

对不起,这两种方法都不起作用。如果我尝试新线程(DownloadAllUpdate).start();,它会给出相同的错误,并且downloadAllUpdater.run()不会更新进度条。如果您使
downloadUpdater
处于可运行状态并每次启动一个新线程,则不应该出现相同的错误,可能是不同的错误?另外,您在线程之间共享的所有变量(
downloadplete
totalBlocksLeft
downloadfiled
)都应该是易变的。这肯定是同一个错误,很明显,它不是线程?我会让变量变得易变,以防万一。好吧,我不能正确地更新代码。您是对的,它现在不会在第二轮抛出错误,但线程不会重新启动。调用
start
并再次启动,或者不调用。您应该在代码中添加一些日志,以便更好地了解执行的内容和时间。谢谢-我知道同步方法,但不知道变量
runOnUiThread(new Runnable() {

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

                        //do you download here

                    }
                });