如何在Android / Java的线程中取消长操作?

时间:2012-11-15 19:29:00

标签: java android multithreading

在执行以下代码时,我希望能够阻止它运行,即使它已经完成了一半。例如,如果我有一个boolean x = true;,那么我想向这个线程/类发送一些stop(ReadJSONFeedMainTask);命令之王。我想取消所有内容,甚至取消onPostExecute()中可能发生的事情。我怎么能这样做?

这是我的代码:

private void doStuff() {
    new ReadJSONFeedMainTask().execute(urlString);
}

private class ReadJSONFeedMainTask extends AsyncTask<String, Void, String> {
    protected String doInBackground(String... urls) {
        return Helper.readJSONFeed(urls[0]);
    }

    protected void onPostExecute(String result) {

        try {      
            dictItems = new ArrayList<HashMap<?, ?>>();
            JSONArray jsonArray = new JSONArray(result);
            Log.i("JSON", "Number of items in feed: " + jsonArray.length());

            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);

                HashMap<String, String> map = new HashMap<String, String>();

                Iterator<?> it = jsonObject.keys();
                while (it.hasNext())
                {
                      // do a bunch of time consuming stuff
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }  
    }
}

4 个答案:

答案 0 :(得分:2)

要取消任务,请执行asyncTaskVariable.cancel()。如果它已经在onPostExecute中,它将不得不完成它 - 你在UI线程上并且无法杀死它。你可以做的最好是设置一个变量来告诉它终止(当然是从另一个线程),并让它定期检查该变量,如果它的设置则返回。

答案 1 :(得分:2)

当x为真时跳过;

 while (it.hasNext() && x == false) // where x is your skip boolean
 {
      // do a bunch of time consuming stuff
 }

并在您要终止的任何其他方法中执行类似操作。

它比在流动中终止它更安全,因为这可能导致异常行为。

答案 2 :(得分:2)

你应该致电

asyncTaskVariable.cancel( true );

这将迫使asynctask停止。

但是,你应该知道它不会立即停止。

如果线程正在等待IO输入,它将处于“阻塞的io状态”。然后它不会停止。如果您无法控制此Helper方法中发生的情况,则无法更改任何内容。但是如果你拥有它,那么你可以遍历输入流并每次读取多个字节(使用缓冲区)。这将为您提供阻止三人的机会。为此做点什么

int readBytes = 0;
while( readBytes != -1 && !Thread.interrupted ) {
   readBytes = bufferedReader.read( buffer );
   if( readBytes >0 ) { 
      stringBuilder.append( buffer, 0, readBytes ); 
   }
}

使用interrupted标志,当你的asynctask被取消时,你将能够停止你的线程。

您应该考虑不使用AsyncTask进行网络操作。它们专为短期生活而设计。

  

AsyncTask旨在成为Thread和Handler的辅助类   并不构成通用的线程框架。 AsyncTasks   理想情况下应该用于短期操作(几秒钟的时间)   大多数。)如果你需要保持线程长时间运行,   强烈建议您使用提供的各种API   java.util.concurrent pacakge如Executor,ThreadPoolExecutor和   FutureTask。

另一种方法是使用Android服务,就像使用RoboSpice库一样。

答案 3 :(得分:1)

为了做到这一点,你需要保留对你班级的引用。例如......

private ReadJSONFeedMainTask foo;

private void doStuff() {
    foo = new ReadJSONFeedMainTask();
    foo.execute(urlString);
}

然后,当你有中断事件时,你可以打电话

foo.cancel(true);

true参数表示立即中断。

编辑我没有注意到你在postexecute中放置了长跑任务。正如gabe正确提到的,即使cancel()也无法帮助你。您需要重构代码以将长运行任务放在doInBackground方法中,以便它可以立即取消,除了如上所述保持对它的引用。