0

I need to calculate a BigDecimal pow (and roots), but for very large numbers this operation takes 10 or more seconds. Therefore I created the following AsyncTask:

class CalculateTask extends AsyncTask<String, Void, String> {
    //...
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        tvStatus.setText("Started calculation...");
    }

    @Override
    protected String doInBackground(String... params) {         
        val2 = val1.pow(largeValue); //Long operation    
    }

    @Override
    protected void onPostExecute(String result) {
        //...
    }
}

And then I call this AsyncTask from an Activity:

CalculateTask calculateTask;
void calculate() {    
    calculateTask = new CalculateTask();
    calculateTask.execute(largeValue);
}

But sometimes it is required to interrupt the calculation from the Activity. Could you please advice, how to interrupt the AsyncTask?

I sow some examples on StackOverflow related to isCancelled(), but I don't know how to apply it here.

ViH
  • 419
  • 2
  • 14

2 Answers2

1

If the long operation really is just one call, you can't apply the standard solution of checking isCancelled() in a loop.

The simple solution would be to just let it run, but make sure the AsyncTask isn't holding onto any hard references to the context. Or just don't worry about leaking a context for a few seconds, and make sure the activity is still running before trying to touch its UI.

The complicated solution would be to implement your own replacement for BigDecimal#pow(...) that checks isCancelled() in its innermost loop.

Kevin Krumwiede
  • 9,868
  • 4
  • 34
  • 82
0

From SDK documentation:

A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true.

If so then add to doInBackground() method condition that checks for isCancelled() method.

@Override
protected String doInBackground(String... params)
{
   while (!isCancelled())
   {
      // do some stuff
      val2 = val1.pow(largeValue); //Long operation
   }
}

EDIT: This code works only if you have multiple power calculations in that loop and then you cancel your task between them.

evilone
  • 22,410
  • 7
  • 80
  • 107
  • That won't work if the long operation is just one call to an external method. `BigDecimal#pow(...)` won't stop just because the calling `AsyncTask` is cancelled. – Kevin Krumwiede Jul 25 '14 at 16:04
  • @KevinKrumwiede Yup, you're right. That won't stop this power calculation. Maybe this must be done by usual threads then? – evilone Jul 25 '14 at 16:10
  • You would do that by starting a `Thread` and calling `interrupt()` on it if you want to cancel it. But `BigDecimal#pow(...)` is not guaranteed to check if the calling thread `isInterrupted()`. The implementation I looked at does not. So you're back to either letting it run or reimplementing `pow(...)` to check the interruption status. – Kevin Krumwiede Jul 26 '14 at 17:55