I want to cancel the Async Task on the particular condition.
I am doing the following stuff:
MyService.java
....
if(condition){
asyncTask.cancel(true); // its return the true as well
}
...
MyAsynTask.java
...
protected Object doInBackground(Object... x) {
while (/* condition */) {
// work...
if (isCancelled()){ // Here task goes in to wait state
break;
}
else{
//continue to download file
}
}
return null;
}
...
Using DDMS I found that task goes into wait State. Any suggestion to resolve this issue will be highly appreciated.
Thanks,
Yuvi
AsyncTask is a piece of work for PoolExecutor. When you execute your first task Executor creates first thread and executes your task on it. After task execution is finished the thread is not deleted. It starts waiting for a new task.
So it is normal to see AsyncTask thread in wait state.
P.S. It's better not to use AsyncTask for longtime operation. Use your own executor or thread.
P.P.S. AsyncTask uses single thread executor since 4.x. Be careful )
after you explicitly call asyncTask.cancel(true);, the onCancelled() method is called. Try overriding the following method:
#Override
protected void onCancelled() {
//what you want to do when the task was cancelled.
}
Related
I have two buttons in my UI.Both button actions i am calling the same async class.when i click on the second button,first button execution of the async thread stops forcebly and start the execution again.
How to stop forceble execution of async thread in android?
To cancel an async task, you may need to call the cancel() method on the task object, with parameter true.
Eg:
yourAsynObj.cancel(true);
also, you need to check if the task is cancelled in your doInBackground method, you can check it as
if(!yourAsynObj.isCancelled){
// do things
} else {
// Cancel doing things
}
private YourAsyncTask mTask;
declare your asyncTask in your activity.
mTask = new YourAsyncTask().execute();
instantiate it like this.
mTask.cancel(true);
kill/cancel it like this.
Should I write smth like that
return task.exec(session, state).get(json_timeout, TimeUnit.MILLISECONDS);
Or I can do like this
task.exec(session, state, result);
return result;
A have already read all documentation that I found, but failed to find an answer. My bad...
Do not use get(). It will block the ui thread until asynctask finishes execution which no longer makes it asynchronous.
Use execute and to invoke asynctask
new task().exec(session, state, result);
Also you can pass the params to the constructor of asynctask or to doInbackground()
http://developer.android.com/reference/android/os/AsyncTask.html
public final Result get ()
Added in API level 3
Waits if necessary for the computation to complete, and then retrieves its result.
You can make your asynctask an inner class of your activity class and update ui in onPostExecute.
If asynctask is in a different file then you can use interface.
How do I return a boolean from AsyncTask?
AsyncTask#get() will block the calling thread.
AsyncTask#execute() will run in a separate thread and deliver the Result in onPostExecute(...).
I would recommend against using the get() method except in special cases like testing. The whole purpose of the AsyncTask is to execute some long-running operation in doInBackground() then handle the result once it's finished.
One example of normal AsyncTask execution would look like:
Task task = new Task(){
#Override
protected void onPostExecute(Result result) {
super.onPostExecute(result);
//handle your result here
}
};
task.execute();
I have a function, AppHelper.isOnline(Context context), I call in various parts of my application to check that a session didn't timeout before making an HTTP request.
public void onClick(View v) {
Intent intent = null;
switch (v.getId()) {
case R.id.buttonPagamenti:
if (AppHelper.isOnline(this))
{
//here AppHelper.isOnline should have finished it's async task
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
break;
...
Inside AppHelper.isOnline(), I am executing an AsyncTask that logs in, thus making a network request, which can't be run on UI because otherwise I get an exception. I need to wait for it to finish BEFORE resuming with the code inside the if. How can I do this ?
Problem is the activity starts firsts, then the AsyncTask executes, so when the activity expects a valid logged in session, it breaks.
You have two options:
Either use the AsyncTask's method get(long timeout, TimeUnit unit) like that:
task.get(1000, TimeUnit.MILLISECONDS);
This will make your main thread wait for the result of the AsyncTask at most 1000 milliseconds (as per #user1028741 comment: actually there is also infinetly waiting method - AsyncTask#get() which might also do the work for you in some cases).
Alternatively you can show a progress dialog in the async task until it finishes. See this thread (No need for me to copy past the code). Basically a progress dialog is shown while the async task runs and is hidden when it finishes.
You have even third option:" if Thread is sufficient for your needs you can just use its join method. However, if the task is taking a long while you will still need to show a progress dialog, otherwise you will get an exception because of the main thread being inactive for too long.
try using
if (AppHelper.isOnline(this))
{
while(!task.isCancelled()){
// waiting until finished protected String[] doInBackground(Void... params)
}
intent = new Intent(this, OrdineCreaActivity.class);
this.startActivityForResult(intent, R.id.buttonPagamenti);
}
For more information read http://developer.android.com/reference/android/os/AsyncTask.html
Rafiq's response did not work for me - the app hung. I think the reason has to do with the nature of isCancelled(): "Returns true if this task was cancelled before it completed normally." If the task completes normally (i.e. is not cancelled) then while(!task.isCancelled()) { } will loop forever.
To solve this create a Boolean flag that you instatiate to false and then flip to true in task.onPostExecute(). Then do while(!flag) { } before switching Activities. Additionally, if you'd like to give the main thread a 'break' to let the AsyncTask process a little faster, you can do try this:
while (!flag) {
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); }
}
It seems to be working well for me.
intent = new Intent(this, OrdineCreaActivity.class);
context.startActivityForResult(intent, R.id.buttonPagamenti);
Write the above lines in onPostExecute() of you AysncTask. Because if we are using AsyncTask it wont wait there until the task complete.
Say I am running
new CommentList().execute(url);
If I am in the doInBackground method and I catch a Null value and inside that null value exception I try running the same one again:
new CommentList().execute(url);
Will it stop running the first one?
Can I do this:
if (result == null) {
cancel(true);
}
#Override
protected void onCancelled() {
new CommentList().execute(commentlinkurl);
}
Basically I don't want the onPostExecute to run if it gets cancelled.
This is not a good idea. You should not be creating new task on a non-UI thread (from within doInBackground method).
From docs:
There are a few threading rules that must be
followed for this class to work properly:
The task instance must be created on the UI thread.
execute(Params...) must be invoked on the UI thread.
Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Edit based on comments:
You can however start the task again inside onPostExecute or onCancelled method. You can simply return some specific result to it from doInBackground or save your Throwable in the AsyncTask member variable to analyze it further:
protected void onPostExecute(Something something) {
if(something == null){
// safe to start new execute task here
}
// or
if(mException instanceof TemporaryIssueException){
// safe to start new execute task here
}
}
I want to stop a AsyncTask thread from another AsyncTask thread. I have tried like
new AsyncTask.cancel(true) to stop the background process but it didn't stop.
Could any one help me on this?
declare your asyncTask in your activity:
private YourAsyncTask mTask;
instantiate it like this:
mTask = new YourAsyncTask().execute();
kill/cancel it like this:
mTask.cancel(true);
The reason why things aren't stopping for you is because the process (doInBackground()) runs until it is finished. Therefore you should check if the thread is cancelled or not before doing stuff:
if(!isCancelled()){
// Do your stuff
}
So basically, if the thread is not cancelled, do it, otherwise skip it :)
Could be useful to check for this some times during your operation, especially before time taking stuff.
Also it could be useful to "clean up" alittle in
onCancelled();
Documentation for AsyncTask:
http://developer.android.com/reference/android/os/AsyncTask.html
Hope this helps!
You may also have to use it in onPause or onDestroy of Activity Life Cycle:
//you may call the cancel() method but if it is not handled in doInBackground() method
if (loginTask != null && loginTask.getStatus() != AsyncTask.Status.FINISHED)
loginTask.cancel(true);
where loginTask is object of your AsyncTask
Thank you.
You can't just kill asynctask immediately. In order it to stop you should first cancel it:
task.cancel(true);
and than in asynctask's doInBackground() method check if it's already cancelled:
isCancelled()
and if it is, stop executing it manually.
I had a similar problem - essentially I was getting a NPE in an async task after the user had destroyed the fragment. After researching the problem on Stack Overflow, I adopted the following solution:
volatile boolean running;
public void onActivityCreated (Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
running=true;
...
}
public void onDestroy() {
super.onDestroy();
running=false;
...
}
Then, I check "if running" periodically in my async code. I have stress tested this and I am now unable to "break" my activity. This works perfectly and has the advantage of being simpler than some of the solutions I have seen on SO.
u can check onCancelled() once then :
protected Object doInBackground(Object... x) {
while (/* condition */) {
if (isCancelled()) break;
}
return null;
}