Is it possible that the android OS may delay or suspend my asynctask for some reason. If so what can I do to ensure that my task (e.g fetching data from database) is not delayed or suspend. Run it on a UI thread maybe but I have read that it is not a good idea as it can freeze the UI and cause lag.
Is it possible that the android OS may delay or suspend my asynctask for some reason.
It might be blocked by another instance of an AsyncTask. By default they run on a single background thread: https://developer.android.com/reference/android/os/AsyncTask.html
If so what can I do to ensure that my task (e.g fetching data from database) is not delayed or suspend.
Investigate what exactly causes the delay. Is it something inside doInBackground method or maybe delay happens before or after the background operation. It can be anything, hard to tell without debugging the code.
Run it on a UI thread maybe but I have read that it is not a good idea as it can freeze the UI and cause lag.
Although AsyncTask is not a good solution in this case, it should work fine if you implement it correctly. Other approaches to consider will be Loaders, or AsyncQueryHandler with ContentProvider. Depends on your use case.
#Override
protected void onPreExecute() {
holdWait = false;
stop = false;
}
#Override
protected Void doInBackground(Void... params) {
synchronized (this) {
while(true) {
if(Work) return null;
if(HaveWork) {
//make some
} else {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
return null;
}
public void mynotify() {
synchronized (this) {
if(holdWait) {
notify();
holdWait = false;
}
}
}
public void setStopWork() {
synchronized (this) {
stop= false;
if(holdWait) {
notify();
holdWait = false;
}
}
}
}
Related
I'm trying to update the UI multiple times in an AsyncTask.
First of all the UI should update, if a request was accepted and later it should run the publishProgress, but If I return a value in the requestAccepted method the other acceptedFiles method will never be executed, but I want it to execute and update the UI before from this task
#Override
protected Void doInBackground(FileInformationHandler... params) {
try {
handler.createSecureSocket("192.168.3.29", 7431);
ProtocolHandler phandler = new ProtocolHandler(handler.getInputStream(), handler.getOutputStream());
phandler.sendInitialisation();
ConfirmationHandler cHandler = new ConfirmationHandler(handler.getInputStream(), handler.getOutputStream());
cHandler.addListener(new ConfirmationReceivedListener() {
#Override
public void requestAccepted(boolean b) {
// Update UI without stopping the asynctask
}
#Override
public void acceptedFiles(int[] ints) {
fileSender.addListener(new ProcessListener() {
#Override
public void processChanged(int i, long l) {
publishProgress(i);
}
});
}
});
} catch (IOException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
First of all you don't need to use an Async task if you are anyways doing the long running operation in a separate thread and have callbacks for different states.
So in your case why can't you simply so all of this in the main thread and in the callbacks just update the UI.
But if you still want to use the Async task then since the doInBackground executes in a separate thread, you can do whatever long running operation is in the method serially and keep using the publishProgress method to update the UI whenever you want. since you are using the callback interface in your case the method will return null and the control with go into the 'onPostExecute'.
IMO using a callback interface in the doInBackground method is not the right approach and defeats the purpose of asyncTask async task.
I must use Thread in an Android project. Sometimes, it works corectly, however sometimes does not; it does not start (does not call SendToServer() method)or it starts but return to another function suddenly (return updated; line)before the thread does not finish.
Note: affected value is bigger than 0, it gives condition and it goes to if statement.
Here is the my code sample;
public static Boolean MyUpdateFunction(MyObject myobject){
Boolean updated=false;
//Code for updating local database
int affected= SqliteDb.update(....);
if(affected>0)
{
//Send updated data to server
//For this I must use Thread(I can't use AsyncThread)
updated=true;
SendToServer();
}
return updated;
}
public static void SendToServer()
{
try{
;
Thread th=new Thread(new Runnable() {
public void run() {
try {
//Create data and send it to server
//.......
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
th.start();
th.join();
}
catch(SQLException e)
{
Toast.makeText(myContext,"ERROR: "+e.getMessage(), Toast.LENGTH_LONG).show();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Other people are correct in that an AsyncTask is the way forward, but the direct problem due to what you're experiencing is this (and as such, I would recommend reading up on how Threading works):
When you start the thread, it begins a new process. The UI thread (which is generally where the majority of your code is) continues. So your code will fire the thread with SendToServer(), and then by definition will immediately return updated, as the UI thread immediately goes to the next line.
What you need is a callback from your Thread, which is handled in the onPostExecute() method of an AsyncTask. There's a good tutorial on how to use them and what they do here
Edit:
I've just seen from a comment above that you can't use Asynctasks, fair enough, but you still need a callback/event fired from your Thread to return any results
Instead of using threads and your variables (updated and affected), you can use AsyncTasks: see: http://developer.android.com/reference/android/os/AsyncTask.html
With AsyncTask, you have some methods which are doing exactly what you want:
onPreExecute
doInBackground
onPostExecute
So, what you can do is to check your condition in onPreExecute, then do your SendToServer in the doInBackground and onPostExecute do what you need.
I need to destroy a thread before application suspend. This is my code:
public class MyThread extends Thread
{
public boolean mRun = false;;
#Override
public void run()
{
while (mRun)
{
.....
}
}
}
Activity:
#Override
public void onPause() {
if (mThread != null)
{
mThread.mRun = false;
try { mThread.join(); }
catch (InterruptedException e) { }
}
super.onPause();
}
But i'm pretty sure that the android system do not wait my thread conclusion and pause my application before it. How can i force thread conclusion?
This is the way, I used in my code meet your requirement.Hope, this will be helping you too. If you find a better solution, Please share it.
In the below snippet, mThread is thread got created in onCreate. OnDestroy is a method that would be called before your activity destroyed.Its a best place to empty the allocated resources.
#Override
public void onDestroy() {
super.onDestroy();
if(null != mThread) {
Thread dummyThread = mThread;
mThread = null;
dummyThread.interrupt(); // Post an interrupt request to this thread.
}
}
Cheers !
Are you sure that you are not getting an InterruptedException?
Try putting a stacktrace in the catch sentence...and also check if your thread isAlive().
You cannot do that. Thread.join is a blocking potentially long operation that must not be done on the UI Thread (onPause being on the UI Thread).
You can ask your thread to stop, (setting mRun to false is a commonly accepted way of doing so), but you cannot exclicitely wait on it.
To be sure , mark the thread as daemon, always check a flag if doing a repetitive task in a thread, like in a loop. Also, call interrupt, which will take care of blocking IO or network calls.
myThread.setDaemon(true)
and
cancelFlag = true;
myThread.interrupt();
I am using an Asynctask as the loop controller for a game and noticed that the thread created kept on running after the activity was finished.
I realised that was the correct behaviour of a separate thread and then I tried hunting down answers on how to end the thread when the app enters onPause.
I found lots of similar questions but no direct answers but eventually came up with a method so I'm going to answer my own question here to hopefully help others in future. (And to receive improvements to my answer as well)
Firstly, AsyncTask have a fully valid cancel() method. Secondly, do not use an AsyncTask for a proper game loop. AsyncTask isn't for long-running operations.
Therefore, skip AsyncTask for your game loop and learn how to properly manage pausing / resuming in an ordinary Thread by reading another answer from me here on SO.
public class CamOverlayTest extends Activity {
//...
public static BackgroundLoop BackgroundLoopTask;
//...
#Override
protected void onResume() {
//...
BackgroundLoopTask = new BackgroundLoop();
BackgroundLoopTask.execute();
}
#Override
protected void onPause() {
//...
BackgroundLoopTask.cancel(true);
}
private class BackgroundLoop extends AsyncTask<Void,Integer,Boolean> {
#Override
protected Boolean doInBackground(Void... arg0) {
int count =0;
while (!this.isCancelled()) {
// Basically, this is where the loop checks if the Aysnctask has been asked to be
// cancelled - if so - it exits.
try {
Thread.sleep(1000);
updatePhysics(count);
} catch (InterruptedException e) {
e.printStackTrace();
}
count +=1;
Log.i("SW","Count: "+count);
publishProgress();
}
return true;
}
#Override
protected void onProgressUpdate(Integer... values) {
// swDrawOnTop is my view
swDrawOnTop.invalidate();
}
//...
}
I have a Service that launches a Thread and a Runnable like so.
t = new Thread(new Runnable() {
public void run() {
doSomething();
}
});
t.start();
The reason for the thread is to perform an Async task doSomething(). For now lets not worry about the other class AsyncTask. I have tried it and it does not work for my case. Edit: I can't use AsyncTask because it is meant for the UI thread only. This piece of code has to operate inside a Service, so nope, no AsyncTask :(
doSomething() contains some external libs so the issue I am having is that it can potentially be hung at one of the commands, without return any value (hence no error checking can even be done)
To work around this, I will want to, at some point of time, destroy the Service.
stopService(new Intent("net.MyService.intent));
This works fine and is easily verified on the phone. However, the Thread which was created above will continue to run even when the Service that spawned it is destroyed.
I am thus looking for the correct commands to insert in the Service's onDestroy() which will clean up the Thread for me.
t.destroy();
t.stop();
are both depreciated and cause application crashes.
I took this code from somewhere
#Override
public void onDestroy() {
Thread th = t;
t = null;
th.interrupt();
super.onDestroy();
}
but it still does not work, the thread continues to run. Any help guys?
The thread destroy and stop methods are inherently deadlock prone and not safe. Their existence also gives the illusion that there might be some way of halting another thread immediately when something else tells it to.
I understand your thinking, from your point of view their is one main thread, and when this thread hasn't received a response from it's worker thread in a while you'd like to kill it and restart it, without caring what it's up to. But the reason those methods are deprecated is you should care what the thread is up to. A lot.
What if the thread has a lock around a variable you need to use later? What if a thread has a file handle open? In all these cases, and many more, simply stopping the thread at it's current operation would leave things in mess -- quite likely your application would just crash further down the line.
So in order for a thread to be interruptible or cancel-able or stoppable, it has to manage this itself. If a thread or operation provides no way for itself to be interrupted, then you cannot interrupt it - it is assumed to do so would be unsafe.
If you runnable is literally
public void run() {
doSomething();
}
then there is no way to interrupt it. One would hope that if doSomething were a long operation that there might be a way to either interact with it incrementally with something like
public void run() {
while (running) {
MyParser.parseNext();
}
}
or to be able to pass in a variable by reference which indicates whether the thread is interrupted or not, and hopefully the method would interrupt itself at suitable location.
Remember a blocking operation is blocking. There is no way to get around that, you cannot cancel it part way through.
Alternative answer
Use the following code:
MyThread thread; // class field
Create and start the thread as you do it right now.
thread = new MyThread();
thread.start();
When the service is destroyed, "signal" the thread to quit
public void onDestroy() {
// Stop the thread
thread.abort = true;
thread.interrupt();
}
Here is thread implementation
//another class or maybe an inner class
class MyThread extends Thread {
syncronized boolean abort = false;
//ugly, I know
public void run() {
try {
if(!abort) doA();
if(!abort) doB();
if(!abort) doC();
if(!abort) doD();
} catch (InterruptedException ex) {
Log.w("tag", "Interrupted!");
}
}
}
You might want to read the following:
How do you kill a thread in Java?
Thread Primitive Deprecation as already pointed by Claszen
http://www.devx.com/tips/Tip/31728 - based my code from here, but there are some issues with the code!
I think that you could rely on catching the exception and not check abort but I decided to keep it that way.
UPDATE
I've seen this sample in codeguru:
public class Worker implements Runnable {
private String result;
public run() {
result = blockingMethodCall();
}
public String getResult() {
return result;
}
}
public class MainProgram {
public void mainMethod() {
...
Worker worker = new Worker();
Thread thread = new Thread(worker);
thread.start();
// Returns when finished executing, or after maximum TIME_OUT time
thread.join(TIME_OUT);
if (thread.isAlive()) {
// If the thread is still alive, it's still blocking on the methodcall, try stopping it
thread.interrupt();
return null;
} else {
// The thread is finished, get the result
return worker.getResult();
}
}
}
Did you check the Java Thread Primitive Deprecation Documentation which is referenced in the Thread API JavaDoc. You will find some hints to handle your problem.
why don't you use an AsyncTask?
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.)
I like to take the following approach:
class MyHandler extends Handler {
final Semaphore stopEvent = new Semaphore(0);
#Override
public void handleMessage(Message msg) {
try {
while (!stopEvent.tryAcquire(0, TimeUnit.SECONDS)) {
doSomething();
if (stopEvent.tryAcquire(SLEEP_TIME, TimeUnit.MILLISECONDS)) {
break;
}
}
} catch (InterruptedException ignored) {
}
stopSelf();
}
}
On service onDestroy just release the stopEvent:
#Override
public void onDestroy() {
myHandler.stopEvent.release();
myHandler = null;
super.onDestroy();
}
Better to use global variable stopThread, stop thread once variable changed to true.
btnStop.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0){
stopThread = true;
}
});
public void run() {
while (!stopThread) {
//do something
}
}
I think the best way to create and communicate with another thread is to use an AsyncTask. Heres an example of one:
public class Task extends AsyncTask<Void, Void, Void> {
private static final String TAG = "Task";
private boolean mPaused;
private Runnable mRunnable;
public Task(Runnable runnable) {
mRunnable = runnable;
play();
}
#Override
protected Void doInBackground(Void... params) {
while (!isCancelled()) {
if (!mPaused) {
mRunnable.run();
sleep();
}
}
return null;
}
private void sleep() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Log.w(TAG, e.getMessage());
}
}
public void play() {
mPaused = false;
}
public void pause() {
mPaused = true;
}
public void stop() {
pause();
cancel(true);
}
public boolean isPaused() {
return mPaused;
}
}
You can now easily use this class, and start the thread by writing:
Task task = new Task(myRunnable);
task.execute((Void) null);
Along with this you can easily pause or stop the thread from looping:
Example of pausing and playing the thread:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (task.isPaused()) {
task.play();
} else {
task.pause();
}
}
});
Example of stopping and starting the thread:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (task.isCancelled()) {
task = new Task(myRunnable);
task.execute((Void) null);
} else {
task.stop();
}
}
});