3

我的活动有一个你可以在下面看到AsyncTask的方法。doInBackground我必须向多个服务器发出多个搜索请求,为了加快执行速度,我使用 JavaExecutorService发出并发请求。

这工作正常,但我希望我AsyncTask停止它正在做的任何事情并退出,如果我调用该AsyncTask.cancel();方法true作为mayInterruptIfRunning参数。这在我需要在Activity退出时停止任务的情况下很有用,例如按下“返回”按钮。

我读过调用 的cancel()方法AsyncTask将阻止该onPostExecute方法被调用,但doInBackground将运行直到完成。

有没有办法,我可以打断我Callables并强迫他们停止他们正在做的任何事情并停止AsyncTask.

为简洁起见,我在此处发布了我的代码的精简版,但我有一堆 a Callables,而不仅仅是一个。

谢谢。

  protected ArrayList<Result> doInBackground(final String... strQuery) {

      ArrayList<Result> objResults = new ArrayList<Result>();
      ExecutorService esrExecutor = Executors.newFixedThreadPool(2);
      Set<Callable<ArrayList<Result>>> setCallables = new HashSet<Callable<ArrayList<Result>>>();

      setCallables.add(new Callable<ArrayList<Result>>() {

          public ArrayList<Result> call() throws Exception {

              try {

                  MySearcher objSearcher = new MySearcher(Finder.this.objContext);
                  ArrayList<Result> objResults = new ArrayList<Result>();

                  objResults = objSearcher.doSearch(strQuery[0]);

                  return objResults;

              } catch (Indexer.LoginException e) {
                  return null;
              }

              return null;

          }

      });


      List<Future<ArrayList<Result>>> lstFutures;

      try {

          lstFutures = esrExecutor.invokeAll(setCallables);

          for(Future<ArrayList<Result>> futFuture : lstFutures){
              if (futFuture.get().isEmpty() == false)
                  objResults.addAll(futFuture.get());
          }

      } catch (InterruptedException e) {
          e.printStackTrace();
      } catch (ExecutionException e) {
          e.printStackTrace();
      }

      esrExecutor.shutdown();

      return objResults;

  }
4

3 回答 3

3

我认为一种解决方案是isCancelled()定期检查您的doInBackground()方法,以检查是否AsyncTask已取消以及是否需要停止您之前正在做的事情。

于 2012-09-19T06:51:02.167 回答
1

这是您迭代并等待的地方:

   for(Future<ArrayList<Result>> futFuture : lstFutures){
          if (futFuture.get().isEmpty() == false)
              objResults.addAll(futFuture.get());
      }

Future的get()方法,Waits if necessary for the computation to complete, and then retrieves its result. 你可以isCancelled() 这样检查,

       for(Future<ArrayList<Result>> futFuture : lstFutures){
           if(isCancelled())
              break;
           else if (futFuture.get().isEmpty() == false)
              objResults.addAll(futFuture.get());
      }
      if(isCancelled())esrExecutor.shutdownNow();
于 2012-09-19T08:06:06.970 回答
0

另一种选择,例如,如果doSearch有一个循环,您可以在不使用isCancelledor的情况下手动完成cancel。您的 MySearcher 类可能具有以下内容。

//in your MySearcher class
private AtomicBoolean cancelled = false;

public ArrayList<Result> doSearch(...){
    while(notFound && !cancelled.get()){
     // keep searching
    }
}

public void cancel(){
    cancelled.set(true);
}

现在您可以从任何地方调用取消。

于 2012-09-19T07:14:04.537 回答