how to wait for Android runOnUiThread to be finished? - java

I have a worker thread that creates a runnable object and calls runOnUiThread on it, because it deals with Views and controls. I'd like to use the result of the work of the runnable object right away. How do I wait for it to finish? It doesn't bother me if it's blocking.

Just scratching out the highlights
synchronized( myRunnable ) {
activity.runOnUiThread(myRunnable) ;
myRunnable.wait() ; // unlocks myRunable while waiting
}
Meanwhile... in myRunnable...
void run()
{
// do stuff
synchronized(this)
{
this.notify();
}
}

Perhaps a little simplistic but a mutex will do the job:
final Semaphore mutex = new Semaphore(0);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
// YOUR CODE HERE
mutex.release();
}
});
try {
mutex.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}

Andrew answer is good, I create a class for easier use.
Interface implementation :
/**
* Events for blocking runnable executing on UI thread
*
* #author
*
*/
public interface BlockingOnUIRunnableListener
{
/**
* Code to execute on UI thread
*/
public void onRunOnUIThread();
}
Class implementation :
/**
* Blocking Runnable executing on UI thread
*
* #author
*
*/
public class BlockingOnUIRunnable
{
// Activity
private Activity activity;
// Event Listener
private BlockingOnUIRunnableListener listener;
// UI runnable
private Runnable uiRunnable;
/**
* Class initialization
* #param activity Activity
* #param listener Event listener
*/
public BlockingOnUIRunnable( Activity activity, BlockingOnUIRunnableListener listener )
{
this.activity = activity;
this.listener = listener;
uiRunnable = new Runnable()
{
public void run()
{
// Execute custom code
if ( BlockingOnUIRunnable.this.listener != null ) BlockingOnUIRunnable.this.listener.onRunOnUIThread();
synchronized ( this )
{
this.notify();
}
}
};
}
/**
* Start runnable on UI thread and wait until finished
*/
public void startOnUiAndWait()
{
synchronized ( uiRunnable )
{
// Execute code on UI thread
activity.runOnUiThread( uiRunnable );
// Wait until runnable finished
try
{
uiRunnable.wait();
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
}
}
}
Using it :
// Execute an action from non-gui thread
BlockingOnUIRunnable actionRunnable = new BlockingOnUIRunnable( yourActivity, new BlockingOnUIRunnableListener()
{
public void onRunOnUIThread()
{
// Execute your activity code here
}
} );
actionRunnable.startOnUiAndWait();

A solution might be to leverage Java's FutureTask<T> which has the benefit that someone else has already dealt with all the potential concurrency issues for you:
public void sample(Activity activity) throws ExecutionException, InterruptedException {
Callable<Void> callable = new Callable<Void>() {
#Override
public Void call() throws Exception {
// Your task here
return null;
}
};
FutureTask<Void> task = new FutureTask<>(callable);
activity.runOnUiThread(task);
task.get(); // Blocks
}
You can even return a result from the main thread by replacing Void with something else.

I think the simplest way to achieve this is using a "CountDownLatch".
final CountDownLatch latch = new CountDownLatch(1);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do something on the UI thread
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Now do something on the original thread
(I believe this question is a duplicate of "How to make timer task to wait till runOnUiThread completed")

In case someone faces this while developing in a Xamarin app I leave here my C# code that made the trick.
My RecyclerView adapter was being set too late so it was returning null in my ScrollListener constructor. This way my code waits for the ui thread to finish the work and release the "lock".
All this is running inside a Fragment (Activity returns the parent activity object).
Semaphore semaphore = new Semaphore(1, 1);
semaphore.WaitOne();
Activity?.RunOnUiThread(() =>
{
leaderboard.SetAdapter(adapter);
semaphore.Release();
});
semaphore.WaitOne();
scrollListener = new LazyLoadScrollListener(this, (LinearLayoutManager)layoutManager);
leaderboard.SetOnScrollListener(scrollListener);
semaphore.Release();
Hope it helps somebody.

This is how I do with Kotlin Extension
Add Extension function to check Thread and run on UI thread
fun Context.executeOnUIThreadSync(task: FutureTask<Boolean>) {
if (Looper.myLooper() == Looper.getMainLooper()) {
task.run()
} else {
Handler(this.mainLooper).post {
task.run()
}
}
}
It will block UI thread and wait for return
fun checkViewShown(): Boolean {
val callable: Callable<Boolean> = Callable<Boolean> {
// Do your task in UI thread here
myView != null && myView?.parent != null
}
val task: FutureTask<Boolean> = FutureTask(callable)
applicationContext.executeOnUIThreadSync(task)
return task.get()
}

Use the AsyncTask class, its methods onPostExecure and onProgressUpdate are executed by the MAIN thread (the UI thread).
http://developer.android.com/reference/android/os/AsyncTask.html
Is the better way for your case!
Hope this can help you.

Related

Can't stop thread

I have these two methods for creating and stopping a thread. However the thread still keeps running, even after the first method is called. (I'm creating an object of the class and calling them from another class).
private Thread thread;
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
sendAlarm = false;
if (!thread.equals(null)) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void triggerAlarm() {
Runnable alarmTest = new Runnable() {
#Override
public void run() {
while (sendAlarm) {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
}
}
};
thread = new Thread(Test);
thread.start();
}
When stopAlarm is called the thread is always null, although it is called after triggerAlarm is called (thread is running).
Your problem is caused by thread scope. Thread scope is created when you create a thread with same variables in the scope but you can't change these variables from outside world. Best practice for managing runnables in android is to use Handler.
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
after definitions, in order to start the runnable:
handler.post(alarmTest,0); //wait 0 ms and run
in order to stop the runnable:
handler.removeCallbacks(alarmTest);
EDIT: wait statement with loop
EDIT: Complete solution
Handler handler = new Handler();
Runnable alarmTest = new Runnable() {
#Override
public void run() {
Log.i(LOG_TAG, String.valueOf(sendAlarm));
handler.post(alarmTest, 5000); //wait 5 sec and run again
//you can stop from outside
}
};
public void stopAlarm() {
Log.i(LOG_TAG, "stopAlarm called");
handler.removeCallbacks(alarmTest);
}
public void triggerAlarm() {
handler.post(alarmTest,0); //wait 0 ms and run
}
Depending on your OS you may find making your thread volatile may fix this.
private volatile Thread thread;
However - there are better ways to do this. One very useful one is using a small (just one entry) BlockingQueue which is polled by the running thread.
// Use a BlockingQueue to signal the alarm to stop.
BlockingQueue<String> stop = new ArrayBlockingQueue<>(1);
public void stopAlarm() {
stop.add("Stop");
}
public void triggerAlarm() {
new Thread(() -> {
try {
while (stop.poll(1, TimeUnit.SECONDS) == null) {
// Stuff
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Clearly you will have to manage edge cases like where someone calls stopAlarm when no alarm is running.

How to know when a thread has completed its task

As I am using gui and I need to create a thread to complete a task. See I want to display a dialog letting the user know the task has been completed I have tried
if(!thread.isAlive()) {
JOptionPane.showMessageDialog(null, "Done");
}
But that doesnt work.
Can anyone help me
Thanks
One option is to do your work using a SwingWorker. Override the done() method and have it notify your GUI that work is complete.
A simple example that nearly matches your use case is shown in the Javadocs at the top of the page:
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
// Here you do the work of your thread
return findTheMeaningOfLife();
}
#Override
protected void done() {
// Here you notify the GUI
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
You could just have the thread print a message as it's last line of code in it's run method:
Thread thread = new Thread() {
#Override
public void run() {
//whatever you want this thread to do
//as the last line of code = the thread is going to terminate
JOptionPane.showMessageDialog(null, "Done");
}
}
thread.start();
If you want the main thread to wait for the thread to finish, in the main thread's code you'd use:
thread.join();
create a listener in your main Thread, and then program your Thread to tell the listener that it has completed.
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final Thread thread);
}
then create the following class:
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
#Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start(); // Start the Thread
then, as each Thread exits, your notifyOfThreadComplete method will be invoked with the Thread instance that just completed. So now you can run any of your code in this method.
Use Callable thread. It will return value,So we can identify that it completed its task.

Run a function synchronously in another thread

How can I run a function synchronously in another thread, meaning the main UI thread has a function that calls another function that does its work on another thread, waits for the new thread to finish and returns the value:
int mainFunction() //this function is on the main UI thread
{
return doWorkOnNewThread();
}
int doWorkOnNewThread()
{
//do work on new thread
}
You can use Async task for this, even though it's asynchronous. You can use the callbacks onPostExecute and onProgressUpdate to update the values as needed. I should also note you probably don't want to do this synchronized as it will block your UI thread which could cause an application not responding alert depending on how long the calculation takes.
There are few ways of executing code in separate threads.
You can read about this here
I think that AsyncTask will do what you want.
protected void onPreExecute () {
// you can show some ProgressDialog indicating to the user that thread is working
}
protected Type doInBackground(String... args) {
doWorkOnNewThread()
// do your stuff here
}
protected void onPostExecute(Type result) {
// here you can notify your activity that thread finished his job and dismiss ProgressDialog
}
You have two way:
1. Asyntask
2. Handler
public static <T> T runSynchronouslyOnBackgroundThread(final Callable<T> callable) {
T result = new Thread() {
T callResult;
#Override
public void run() {
try {
callResult = callable.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
T startJoinForResult() {
start();
try {
join();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return callResult;
}
}.startJoinForResult();
return result;
}

Regarding creating synchronization mechanism [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Testing a multithreaded Java class that runs the threads sequentially
Please don't treat this below question as a duplicate one..!
I have developed a class that lets multi-threads to run sequentially, one at a time and in order. All the application code between this class' claimAccess function and release Access function will be executed only in one thread at one time. All other threads will wait in the queue until the previous thread completed.Please advise I want to test my class by writing a piece of code in main() method itself .
import java.util.ArrayList;
import java.util.List;
public class AccessGate {
protected boolean shouldWait = false;
protected final List waitThreadQueue = new ArrayList();
/**
* For a thread to determine if it should wait. It it is, the thread will
* wait until notified.
*
*/
public void claimAccess() {
final Thread thread = getWaitThread();
if (thread != null) {
// let the thread wait untill notified
synchronized (thread) {
try {
thread.wait();
} catch (InterruptedException exp) {
}
}
}
}
/**
* For a thread to determine if it should wait. It it is, the thread will be
* put into the waitThreadQueue to wait.
*
*/
private synchronized Thread getWaitThread() {
Thread thread = null;
if (shouldWait || !waitThreadQueue.isEmpty()) {
thread = Thread.currentThread();
waitThreadQueue.add(thread);
}
shouldWait = true;
return thread;
}
/**
* Release the thread in the first position of the waitThreadQueue.
*
*/
public synchronized void releaseAccess() {
if (waitThreadQueue.isEmpty()) {
shouldWait = false;
} else {
shouldWait = true;
// give the claimAccess function a little time to complete
try {
Thread.sleep(10);
} catch (InterruptedException exp) {
}
// release the waiting thread
final Thread thread = (Thread) waitThreadQueue.remove(0);
synchronized (thread) {
thread.notifyAll();
}
}
}
}
Now my main method would be ..
public static void main (String args[])
{
}
please advise how I spawn thr threads in my my main method to test the above class..!!Please advise
This should get you started...
public static void main (String args[])
{
AccessGate gate = new AccessGate();
// create as many threads as you like
Thread t1 = new MyThread(gate);
Thread t2 = new MyThread(gate);
// start all the threads you created
t1.start();
t2.start();
}
class MyThread extends Thread {
AccessGate gate;
public MyThread(AccessGate g) {
gate = g;
}
public void run() {
gate.claimAccess();
// Do something or print something.
// Could output several statements.
// Why not do a sleep as well to see if other threads interrupt
// this code section.
gate.releaseAccess();
}
}
Consider using Executors.newSingleThreadExecutor(). This is a thread pool with only one thread executing tasks. Next task will start execution only after first task is finished:
Executor executor = Executors.newSingleThreadExecutor();
Future<String> future1 = executor.submit(new Callable<String>() {
#Override
String call() throws Exception {
// my first task
}
});
Future<String> future2 = executor.submit(new Callable<String>() {
#Override
String call() throws Exception {
// my second task
}
});
...
You can retrieve result of task execution via Future API, also it allows you to track status of each job.

Thread wait in Android

i have one problem with handling the thread in android ,in my class i have to create one thread which create some UI after that thread finish i will get some value ,here i want to wait my Main Process until the thread complete it process but when i put wait() or notify in Main process thread does not show the UI in my application
this is sample code
protected void onCreate(Bundle savedInstanceState) {
downloadThread = new MyThread(this);
downloadThread.start();
synchronized(this){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
String test=Recognition.gettemp();
public class MyThread extends Thread {
private Recognition recognition;
public MyThread(Recognition recognition) {
this.recognition = recognition;
// TODO Auto-generated constructor stub
}
#Override
public void run() {
synchronized(this)
{
handler.post(new MyRunnable());
}
notifyAll();
}
}
}
static public class MyRunnable implements Runnable {
public void run() {
settemp(template);
}
}
}
public static String gettemp() {
return template;
}
public static void settemp(String template) {
Recognition.template = template;
}
}
here i will not use AsynTask because i have some other issue that is reason i choose Thread even now the problem is Thread wait do any give the suggestion for this
- Use java.util.CountDownLatch , here you can let some process complete before kick-off some other code.
- countDown() and await() will be of use to you.......
See this example of CountDownLatch:
http://www.javamex.com/tutorials/threads/CountDownLatch.shtml
Use the logic below :-
new Thread(new Runnable()
{
#Override
public void run()
{
//do the code here such as sending request to server
runOnUiThread(new Runnable()
{
#Override
public void run()
{
//do here the code which interact with UI
}
});
}
}).start();
What do you expect to happen if you freeze the main UI thread?
You should be using an ASyncTask to show your gui in the onPreExecute method, do the task in doInBackground then display the result in the onPostExecute method.
As a plus you can update the progress using onProgressUpdate too.
This is not an solution just a advice on how should you structure you activity/app.
You should never block the main thread by calling wait() its a bad user experience and not advised. It would also case a Android Not Responding (ANR) popup.
You can have you thread updating the UI from the background and let the UI to be responsive. Load the static part of your UI in onCreate() and then fire up the background thread to lazy load rest of the component.

Categories

Resources