This question already has answers here:
Ideal way to cancel an executing AsyncTask
(9 answers)
Closed 5 years ago.
I have a class name is GetData that extends from AsyncTask. In other class I have an object from GetData and with this codes I use that:
GetData getData = new GetData();
getData().execute();
I want to stop this thread when a button clicked. I do this with:
getData().cancel(true);
I want to know if I canceled thread while it is in doInBackground, it stopped or it goes to onPostExecute and then stop?
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
For further details visit:
https://developer.android.com/reference/android/os/AsyncTask.html
Just like:
onPostExecute(Result result)
{
}
you can override a method for cancel to update your UI accordingly when your asyncTask is cancelled as follows:
onCancelled(Result result)
{
// here you can handle situation according to your requirements
}
So point of your interest here is that whenever you cancel your task before it enters into onPostExecute it will not go into onPostExecute but will jump to onCancelled. You can also call task.cancel(true); in postExecute according to your condition by applying required checks.
From the Android documentation:
Calling this method will result in onCancelled(Object) being invoked on the UI thread after doInBackground(Object[]) returns. Calling this method guarantees that onPostExecute(Object) is never invoked.
So onPostExecute will not be called.
Related
I have been checking similar questions.
This one is quite similar what I want to ask but not really I have the answer. Also This question I have checked.
Question that I have is that I have a SwingWorker which does long processes in the background.
#Override
protected final List<Object> doInBackground() throws Exception
{
//Should I add if(this.isCancelled) here?
List<Object> objectList = someFecthingMethod();
//Should I add if(this.isCancelled) here?
objectList.forEach(object -> executor.submit(new Helper(object));
this.latch.await();
//Should I add if(this.isCancelled) here?
someOtherLongRunningMethodBasedOnHelperResults();
}
In scratch I have a code like that. This runs when calculate button of mine which triggers the worker when it is clicked. I also want to be able to cancel it. I have written needed method stop() where it has cancel() method of worker itself.
Like below in my Worker Class I have my stop method like below:
#Override
public boolean stop()
{
return this.cancel( true );
}
When I call this method, I check in doInBackground(), this.isCancelled() returns true.. But anyway it keeps executing the methods within doInBackground().
So my question is that, should I be adding if(this.isCancelled()) check before every method in doInBackground() to stop it immediately, is there any better way to do stop it from executing when its canceled?
Thank you in advance.
You can create a wrapper around that provides the ability to cancel the latch. It will need to track the waiting threads and release them when they timeout as well as remember that the latch was cancelled so future calls to await will interrupt immediately.
I've noticed on the documentation for AsyncTask here that you can use a method called get() to retrieve your result once the work on the thread is done. The documentation says that it
Waits if necessary for the computation to complete, and then retrieves its result.
Does that mean if I have this line of code:
List<Data> data = someAsyncTask.execute.get();
in the main UI thread, does it wait for the task to complete before executing any code after it? If so, this would render the use of AsyncTask useless. What am I missing here?
Is AsyntTask.get() an alternative to using onPostExecute() to return data to the main thread? If so, is it safe? Or is its use for something completely different?
If you call AsyncTask.get() and the task is not completed, then current thread will wait (and can be interrupted).
You right, calling this method in UI thread makes AsyncTask useless. But you can call it in another thread which need result of this task for further execution.
I am coding an android game in Eclipse with java. The main goal is to wait for a thread to finish, then to set a boolean to true. The reason is that when a user clicks a button it will only run if the boolean is true. However, when I call a method, it creates a thread and does its thing, then when it is done, it sets the boolean to true. However, it automatically sets the boolean to true while the thread is still running, and so the user can click the button (which messes some things up). Is there a way to wait for a thread to finish without freezing the screen? (thread.join() seems to be freezing it)
Any help is appreciated.
Seems like you don't really need to wait until the thread is done to continue, the way I see it you only need to be notified once it's done, the simplest approach for it would be passing a "callback listener" object to the thread, and execute it when done, this will let you know that you are ready to continue, OR a better approacch would be an AsyncTask which will allow you to do everything in background and when done you can use the onPostExecute method, hope this helps.
This is the way you create and add a callback to be notified when your thread has completed:
//Create your callback listener interface...
public interface MyThreadListener{
public void threadFinished();
}
//This is the method that runs some functionality in a separate thread
public void executeTaskInSeparateThread(final MyThreadListener listener){
new Thread(new Runnable() {
#Override
public void run() {
// DO your long task here...
//Notify when done before leaving run method...
listener.threadFinished();
}
}).start();
}
//Use it like this
//Create the implementation of the listener you want (this is something like what you usually do for buttons or any other android listener)
MyThreadListener listener = new MyThreadListener() {
#Override
public void threadFinished() {
//Do whatever you want when notified...
//NOTE: This method will be called on a separated thread too, you cannot modify views...
}
};
executeTaskInSeparateThread(listener);
Once the thread completed it will execute the listener and will let you know is done...
Regards!
Q: Why not set the button to "disabled" when you start the thread (btn=.setEnabled(false);), then have the thread set the button to "enabled" just before it exits?
And yes, calling "thread.join()" (or ANY blocking call) from your UI thread will indeed "freeze" it :)
PS:
Are you using a Java thread, or an Android "Asynch Task"? Here's an excellent tutorial on the latter:
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
Use an AsyncTask. In onPreExecute() disable your button so the user cannot click it again.
In onPostExecute method enable the button again. Do the time consuming logic in the doInBackground method.
try to create a Task extends AsyncTask, override the doinBackground mothed,Then put "time-consuming operation" in it. When your task done,it'll goto "onPostExecute",just use an Interface call back to the Actiity and enable the Button . When you use the AsyncTask you should know that: The Default AsyncTask has got a "pool",System allow 5 instace of AsyncTask ,if you got more than 5 Task,you should create a no limit pool.
My English is so so bad,lol.
I have a AsyncTask class that is separate from the MainActivity.
protected void onPostExecute(ArrayList<String> result) {
System.out.println("flag1");
MainActivity.myLst=new ArrayList<String>();
MainActivity.myLst=result;
}
then I have the following code in my MainActivity.
public void onCreate(Bundle savedInstanceState) {
new AsyncTask().execute();
System.out.println("flag2");
System.out.println(myLst.size());
}
The program outputs the flag2 first and myLst.size is 0. If I negative to other activity and then come back to the main activity and myList.size has the correct size. I thought It should output everything and do the work in AsyncTask before the MainActivity.
The AsyncTask doesn't "do the work before MainActivity", that would defeat the purpose of an AsyncTask.
What you want to do is write up an interface to pass the value back to your Activity. This answer has a good example of that.
You're creating an AsyncTask to do stuff asynchronously.
You're saying to another thread that it has work to do, but you're not waiting his result to do yours, that's why "flag2" is written before the other.
if you want to wait the result, you need to implement a callback in onPostExecute()
Asynchronous means that it may be out of order. An asynchronous task often launches another thread that does the work in parallel, or in the background, to the main thread. You absolutely cannot assume that the asynchronous task will be completed when execute() returns!
Like other have said and like I have said in the comments to your post, async means asynchronously, and in your case means it will probably finish the onCreate code before finishing the async task.
Either put the AsyncTask class inside your MainActivity (and call some method to print on PostExecute), or implement an Observing/Observer style in your activities to be able to notify your main activity that the async task is over.
You can just overwrite the onPostExecute() method inside the the code that calls the Asynctask.
For example,you have a AsyncTask called myAsyncTask. Then in your Activity do it like this:
new myAsyncTask() {
#Override
protected void onPostExecute( Result result ) {
super.onPostExecute( result );
// Do something with result here
}
}.execute(value1);
I had the same issue, I wanted to get the result inside a fragment....
Look at this topic
I would like to handle a return result from an AsyncTask outside of the class.
Is there any downside using, for example, Location loc = TheClass.execute().get();? Should I handle the result in onPostExecute inside the class instead?
The get() method is not well method for it, cause it stoped UI-thread
The only place where you can be assured that the operation you have started in doInBackground() has completed is the callback method onPostExecute(). So using a get() is not such a wise idea as far as AsyncTask is concerned.
get()
The purpose, of get(), is to block until the result is obtained. This
could be useful, for example, if you have multiple tasks, where one uses
another. One task could start another and call get() to wait for it to
finish before continuing with its own work.
onPostExecute (Result result)
Runs on the UI thread after doInBackground(Params...). The specified result is the value returned by doInBackground(Params...).
This method won't be invoked if the task was cancelled.
get() make you (current Thread) wait until the result come and onPostExecute did work Asynchronously and work like a call back when the background work has been completed.
http://developer.android.com/reference/android/os/AsyncTask.html#get()
public final Result get ()
Waits if necessary for the computation to complete, and then retrieves its result.