2012-07-17 29 views
8

Desidero attendere due attività per terminare, quindi restituire il risultato, ma a volte viene visualizzato questo errore. Perché? Da dove proviene CancellationException?CancellationException quando si utilizza ExecutorService

public class ShouldVoteTask extends AbstractWorkerTask<Void, Void, Boolean> { 
    private final int placeID; 
    private final int userID; 

    public ShouldVoteTask(final int placeID, final int userID) { 
     this.placeID = placeID; 
     this.userID = userID; 
    } 

    @Override 
    protected Boolean doInBackground(final Void... params) { 
     try { 
      // Prepare callables. 
      final IsMaxRatingCallable call1 = new IsMaxRatingCallable(placeID); 
      final DidVoteCallable call2 = new DidVoteCallable(placeID, userID);   
      final List<Callable<Boolean>> callables = new ArrayList<Callable<Boolean>>();   
      callables.add(call1); 
      callables.add(call2); 

      // Execute them. 
      final ExecutorService service = Executors.newFixedThreadPool(2);    
      final List<Future<Boolean>> futures = service.invokeAll(callables, 5, TimeUnit.SECONDS); 

      // Check the result. 
      boolean result = true; 
      for(final Future<Boolean> future : futures) { 
       if(future.get()) { 
        result = false; 
       } 
      } 

      return result; 
     } catch (final InterruptedException e) { 
      e.printStackTrace(); 
     } catch (final ExecutionException e) { 
      e.printStackTrace(); 
     } 
     return false; 
    } 
} 

private class IsMaxRatingCallable implements Callable<Boolean> { 
    private final int placeID; 

    public IsMaxRatingCallable(final int placeID) { 
     this.placeID = placeID; 
    } 

    @Override 
    public Boolean call() throws Exception { 
     return Places.isMaxRating(placeID);   
    } 
} 

private class DidVoteCallable implements Callable<Boolean> { 
    private final int placeID; 
    private final int userID; 

    public DidVoteCallable(final int placeID, final int userID) { 
     this.placeID = placeID; 
     this.userID = userID; 
    } 

    @Override 
    public Boolean call() throws Exception { 
     return Votes.didVote(placeID, userID);   
    } 
} 

errore

E/AndroidRuntime(19014): FATAL EXCEPTION: AsyncTask #1 
E/AndroidRuntime(19014): java.lang.RuntimeException: An error occured while executing doInBackground() 
E/AndroidRuntime(19014): at android.os.AsyncTask$3.done(AsyncTask.java:200) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.setException(FutureTask.java:125) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
E/AndroidRuntime(19014): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088) 
E/AndroidRuntime(19014): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581) 
E/AndroidRuntime(19014): at java.lang.Thread.run(Thread.java:1027) 
E/AndroidRuntime(19014): Caused by: java.util.concurrent.CancellationException 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.get(FutureTask.java:83) 
E/AndroidRuntime(19014): at com.vfa.android.planet.task.ShouldVoteTask.doInBackground(ShouldVoteTask.java:43) 
E/AndroidRuntime(19014): at com.vfa.android.planet.task.ShouldVoteTask.doInBackground(ShouldVoteTask.java:1) 
E/AndroidRuntime(19014): at android.os.AsyncTask$2.call(AsyncTask.java:185) 
E/AndroidRuntime(19014): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306) 
E/AndroidRuntime(19014): ... 4 more 
+0

Quale linea è la linea 43? E cosa c'è nella linea 1? È davvero strano che la traccia dello stack mostri la linea 1. –

+0

43 >>> if (future.get()) {Cosa c'è che non va? – Emerald214

+0

Immagino che uno dei tuoi callable abbia fatto un'eccezione. Potresti pubblicare il codice per quelli? –

risposta

20

vi chiediamo il vostro servizio esecutore per eseguire i vostri callable con un timeout di 5 secondi. Secondo the javadoc:

compiti che non hanno completato [entro la fine del timeout] vengono annullate

mia ipotesi è che future.get() getta un CancellationException perché il timeout è stato raggiunto e l'esecutore chiama future.cancel() .

Si potrebbe o:

  • aumentare il timeout
  • prendere un InterruptedException nel vostro callable per gestire la cancellazione con grazia
+0

Ma 'CancellationException' non estende' InterruptedException' giusto? –

+0

BTW, sto trattando 'InterruptedException' attorno a' invokeAll' e otteniamo ancora 'CancellationException' –

+0

@ LuísSoares No, non lo è. – assylias

Problemi correlati