1

在执行以下代码时,我希望能够阻止它运行,即使它已经完成了一半。例如,如果我有一个,那么我想向这个线程/类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

4 回答 4

2

你应该打电话

asyncTaskVariable.cancel( true );

这将强制异步任务停止。

但是,您应该知道这不会立即停止。

如果线程正在等待 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 被设计为围绕 Thread 和 Handler 的辅助类,并不构成通用线程框架。AsyncTasks 最好用于短时间的操作(最多几秒钟)。如果您需要保持线程长时间运行,强烈建议您使用 java.util.concurrent 包提供的各种 API,例如Executor、ThreadPoolExecutor 和 FutureTask。

另一种方法是使用 Android 服务,例如使用RoboSpice库。

于 2012-11-15T19:48:14.073 回答
2

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

于 2012-11-15T19:31:37.910 回答
2

当 x 为真时跳过

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

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

它比在流程中终止它要安全得多,因为这可能会导致异常行为。

于 2012-11-15T19:32:19.657 回答
1

您需要保留对您的班级的引用才能做到这一点。例如...

private ReadJSONFeedMainTask foo;

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

然后稍后当您有中断事件时,您可以调用

foo.cancel(true);

true 参数表示立即中断。

编辑 我没有注意到你在 postexecute 中放置了 longrunning 任务。正如 gabe 正确提到的那样,即使 cancel() 也无济于事。您将需要重构代码以将长时间运行的任务放入doInBackground方法中,以便它可以立即取消,此外还要像上面那样持有对它的引用。

于 2012-11-15T19:34:42.500 回答