I am developing an application using Android SDK. In this application I am facing a problem when an Activity starts a Thread. The new Thread starts an AsyncTask, but the Thread has to wait for completion of the AsyncTask execution.
Is it possible to start AsyncTask in a thread, and if so, how should it be implement?
Please can anyone share your experience with me about this kind of tasks.
Thanks in advance
You should not create an AsyncTask from a thread other than main thread.
If you should wait anyway, why create AsyncTask? perform it on the thread.
just say thread to sleep for some times and then check a variable again like this
in below code someValue was setted in asynctask postExecute method
new Thread(new Runnable(){
#Override
public void run(){
while(!someValue) {
try {
Thread.sleep(200);
} catch {
Log.i("LOG", "ERROR");
}
}
Log.i("LOG", "Async Task Finished");
}
}).start();
Related
Whenever this code is executed the application crashes, but when a handler is used the application works as expected.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
//this code needs to be inside a Handler ??
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
//this code needs to be inside a Handler ??
}
};
Thread thread = new Thread(r);
thread.start();
}
Here all the answer have mentioned use of handler is used in Android with UI thread. But Let me add more to it.
If you have gone Android documentation/tutorial you would know that
When an application component starts and the application does not have
any other components running, the Android system starts a new Linux
process for the application with a single thread of execution. By
default, all components of the same application run in the same
process and thread (called the "main" thread or uiThread).
for more info refer
Now coming to your mentioned example; you have created another thread using Runnable...so there might be scenario you need thread(s) other then just mainThread in Android Application.
If you are good in JAVA Threading concept then you would know how Interthread communication happens and for different ways how it can be done refer
So coming back to question in android we have mainThread or uiThread so called which holds our ui i.e. view component. These component are private to mainThread so other thread cannot access it...which has been mentioned in previous answer. This is where Handler comes into picture you do not need to worry how your message would be passed from one thread to another.
Handler
There are two main uses for a Handler: (1) to schedule messages and
runnables to be executed as some point in the future; and (2) to
enqueue an action to be performed on a different thread than your
own.When posting or sending to a Handler, you can either allow the
item to be processed as soon as the message queue is ready to do so,
or specify a delay before it gets processed or absolute time for it to
be processed. The latter two allow you to implement timeouts, ticks,
and other timing-based behavior.
For more info refer docs AND
For more info with handler and UI thread
Code that deals with the UI should be run on the UI (main) thread.
You (probably) create a handler on the UI thread, so all messages sent via it will run on that thread too.
The Runnable is use for background process(background thread) and textview is in your UI thread so background thread can't communicate with foreground thread so it will gives you error and crashes your application.you can also use the runOnUiThread. example.
Runnable r = new Runnable() {
#Override
public void run() {
long futuretime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis()<futuretime){
synchronized (this){
try {
wait(futuretime - System.currentTimeMillis());
} catch (Exception e) {}
}
}
try {
// code runs in a thread
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView time = (TextView)findViewById(R.id.timedisplay);
time.setText("Changed Man!!");
}
});
} catch (final Exception ex) {
Log.i("---","Exception in thread");
}
}
};
Thread thread = new Thread(r);
thread.start();
The reason why your app crashes is that you modify View from a non-UI thread.
If you do it using a Handler that belongs to UI-thread this works as expected.Update
If you need to run Runnable to modify UI you may choose from:
1) yourActivity.runOnUiThread(Runnable r)
2) yourHandlerOnUIThread.post(Runnable r)
3) yourView.post(Runnable r)
Stop a thread like:
new Thread ( new Runnable() {
public void run(){
if ( condition ) return; // this will stop the thread.
}
}).start();
is correct/safe?
Certainly. The Thread will then finish and can be joined with. The thread would also exit if you threw a RuntimeException or just let the code run off the end of the run() method obviously.
A thread stops when it's run() method returns. It doesn't really matter what logic is used inside run() to decide when or how to return. Your code is perfectly correct and safe.
Yes, it is correct and safe...
I created an asynctask and in its doInBackground() method i started a thread like this:
private class myAsyntask extends Asynctask{
doInBackground(){
Thread t = new Thread(new Runnable(){
public void run()
{
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
});
}
onPostExecute(){
//do something related to that variable
}
}
problem I am facing is after 1st iteration of Thread.sleep() , onPostExecute() is called , instead I thought that asynctask will run this thread on background and when that boolean is true onPostexecute() is called.I am not able to understand why this happens ?
AsyncTask automatically creates a new Thread for you, so everything you do in doInBackground() is on another thread.
What you are doing is this:
AsyncTask creates a new Thread and runs doInBackground().
a new Thread (t) is created from the AsyncTask-Thread.
doInBackground() is completed, as all it does is create the Thread t and thus jumps to onPostExecute().
Thread t would still be running in the background (however, you do not call start() on t, meaning that it is not started).
Instead you want your doInBackground() method to look something like this:
doInBackground(){
while(someBoolean!=true){
//Perform some repeating action.
Thread.sleep(100);
}
}
First of all, in your code you don't even start thread t, so all that happens in doInBackground is creation of new thread and then moving on to onPostExecute().
Secondly, you don't even need separate thread, since doInBackground() handles this for you, so you can just use something like
doInBackground(){
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
if you wish, however, to stick with separate thread, you can start thread and wait for it's completion by using .join(); like
doInBackground(){
Thread t = new Thread(new Runnable(){
public void run() {
while(someBoolean!=true){
Thread.currentThread.sleep(100);
}
}
});
t.start();
t.join();
}
onPostExecute can only be called when doInBackground has return-ed. In your code, the only possible way this can happen is sleep throwing an Exception (InterruptedException??)
I have a gui thread starting a new thread to do some busy things. The GUI thread will wait the worker thread to be completed, in the mean time the GUI need to be responsive.
Psedo code:
main thread:
start_thread();
wait_thread_done();
work thread:
doing_sth();
notify_main_thread();
What is the easiest way to do this in android?
The easiest way to do this is with Android's AsyncTask. The documentation is here
http://developer.android.com/reference/android/os/AsyncTask.html
And you can call Activity.runOnUiThread() to update the UI from your background task.
A small working snippet :
new Thread() {
public void run() {
handler.post(new Runnable() {
public void run() {
try{
// **Do the GUI work here**
} catch (Exception e) { }
}});
};
}.start();
Call Activity#runOnUiThread(Runnable), the Runnable you pass to that method will execute on the GUI thread.
Or use an AsyncTask - which is the proper way to do it.
waiting for result will make gui thread unresponsive. you need to use AsyncTask and override onPostExecute to perform operation required when background thread is done
At a certain point of my AsyncTask, after some validations have been done, I need to spawn off another thread to do some other work. So I'd like two background threads at this point, each doing it's own thing (approx 2-3 seconds to execute each). The idea is to maximize performance on dual core processors like Atrix.
Is it acceptable to create another asynctask & execute it from the first one? Can anyone suggest a better way of doing this?
Thanks!
EDIT: I'm wondering what publishProgress() from the second task would even do... since it was not started from an Activity?
Is it acceptable to create another
asynctask & execute it from the first
one?
Yes, but only inside onProgressUpdate() or onPostExecute() since these methods runs on the UI thread. Therefore, start the second AsyncTask on the UI thread by choosing one of the two methods listed above.
I'm wondering what publishProgress()
from the second task would even do...
since it was not started from an
Activity?
It does exactly the same thing, since you are starting it from the UI thread.
If you are looking for a mechanism of executing multiple async tasks, from 3.0 and above it supports a method called executeOnExecutor which will allow you to schedule tasks in parallel on a pool of thread managed by Async Task.
An AsyncTask is useful for doing some background work while communicating with the main thread to handle UI changes. It appears that this is not your case.
Besides, an AsyncTask must be executed from the main thread. From the AsyncTask reference:
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.
You can a take a look at this article and see what fits you best.
This can be done using message passing concurrency and a single handler. Proof of concept code follows:
private Handler myHandler= new Handler(){
#Override
public void handleMessage(Message msg){
switch(msg.what){
case 0:
Toast.makeText(Main.this,"Message0", Toast.LENGTH_SHORT).show();
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(3000);
}
catch(Exception e){}
myHandler.sendEmptyMessage(2);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
break;
case 1:
Toast.makeText(Main.this,"Message1", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(Main.this,"Message2", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
break;
}
}
};
I launched the first thread on a button click as in:
ON CLICK HANDLER
threadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread thread= new Thread( new Runnable() {
public void run() {
try {
Thread.sleep(1000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(0);
try {
Thread.sleep(3000);
}
catch(Exception e){
}
myHandler.sendEmptyMessage(1);
}
});
thread.setDaemon(true); // <== I am a service provider. KILL ME if the non-daemon thread ConfuseText quits
thread.start();
}
});
The calls to thread sleep is to mimic a time intensive task.