cannot stop progress bar on Android using Thread.interrupt - java

I am running into a minor issue that I don't understand. I have a simple progress bar but Thread.interrupt does not stop the thread. I have to hack it a global variable. I wonder if anyone can stop the issue.
I tried this thread, but did not work for me:
How to stop a thread(progressbar) in android
here's the code with the hacks
// Start lengthy operation in a background thread
calcThread = new Thread
(
new Runnable()
{
public void run()
{
Thread current = Thread.currentThread();
//while (!current.isInterrupted()) // this does not
while (threadLoop) // this hack works
{
doWork();
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
// Update the progress bar
mHandler.post(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
}
});
}
Log.d(TAG, "out of thread loop");
}
}
);
calcThread.start();
now where I try to stop the thread
public void onClickAbout(View view)
{
if (view.getId() == R.id.buttonAbout)
{
Log.d(TAG, "onButtonPressed");
calcThread.interrupt(); // This does not work
threadLoop = false; // this works.
}
}
Why do I have to hack a global? In other words, why Thread.interrupt does not stop the thread.
thx!

Why don't you try the following
Thread background = new Thread() {
public void run() {
try{
for(int s=0;s<=100;s++)
{
s=s+20;
sleep(1000);
progressbar.setProgress(s);
}
}catch(InterruptedException e){
e.printStackTrace();
}finally{
//do some thing after you finish thread
}
}
};
background.start();

It doesn't work because you're catching InterruptedException and ignoring it. The thread is no longer interrupted after the exception is thrown. (See this Q&A.) But k0sh is right, you should use an AsyncTask.

Related

Trying To Delay In Java Multiple Times

Need To Do One Animation, Sleep 1000 Then Do The Next Sleep 1000 And So On, Instead It Sleeps For The Entire Time Then Plays All Animations At Once. No Idea What Im Doing.
Tried Timers, Running The Animation Before The tread.sleep And Using A While Loop Instead Of A For.
private void playLaunchAnimation()
{
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fadein);
for(int i=0; i < buttons.size();i++)
{
try {
Thread.sleep(1000);
buttons.get(i).startAnimation(animation);
} catch (Exception e){
/*
main declares that it throws InterruptedException. This is an exception that sleep throws when another thread interrupts the current thread while sleep is active. Since this application has not defined another thread to cause the interrupt, it doesn't bother to catch InterruptedException.
*/
}
}
}
Hi, Make sure this code helps you
public static void main(String[] args) throws Exception {
for(int i=0; i < 10;i++) {
try {
Thread.sleep(1000);
System.out.println(i);
if(i==9) {
i=0;
}
} catch (Exception e){
System.out.println("error");
}
}
}
(Answer assumes Android which wasn't entirely clear in OP.)
This is somewhat of a lazy way to do it - but maybe get you thinking. It would
be more interesting to have the handler invoke the next handler so only one handler is declared - but that would be a little more work.
private void playLaunchAnimation() {
final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fadein);
for(int i=0; i < buttons.size();i++)
{
// Create a handler on the UI thread to execute after a delay.
// The delay is a function of loop index.
//
// It may be necessary to declare buttons final - but your
// OP did not list where it is defined.
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
buttons.get(i).startAnimation(animation);
}
}, ((i+1)*1000));
}
}
References:
How to call a method after a delay in Android
Android basics: running code in the UI thread
It sounds like you are calling Thread.Sleep from the User Interface thread. This will ultimately result in the entire User Interface freezing up for the duration of the sleep. What you really want is to launch sleep from a background thread.
For example:
AsyncTask.execute(new Runnable() {
#Override
public void run() {
for(int i=0; i < buttons.size();i++)
{
try {
Thread.sleep(1000);
activity.runOnUiThread(new Runnable() {
buttons.get(i).startAnimation(animation);
});
} catch (Exception e){}
}
});
Another way you could do this using post delay:
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
buttons.get(i).startAnimation(animation);
new android.os.Handler().postDelayed(this, 1000);
}
},
1000);

Thread won't enter synchronized block

I have a Button in my android app which must run a continuous action while holding it down, for that I created an onTouchListener to handle such issue, my structure is when catching ACTION_DOWN event a thread with a while(true) loop runs, then when catching ACTION_UP event that thread stopped via wait() in order to resume it's looping again upon holding down, the problem is that when trying to execute thread.wait() the thread doesn't enter the synchronized block and doesn't wait, but it stops the execution of runOnUIThread which exists in that thread, and after I press any button after that the app crashes and gives me ANR Exception : Input dispatching timed out:
// the thread declaratrion
test = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
// still loops here
value = value + 1;
runOnUiThread(new Runnable() {
public void run() {
// doesn't go here anymore
mTextView.setText(Integer.toString(value));
}
});
// still loops here
synchronized (test) {
try {
Thread.sleep(150);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
});
// the onTouchListener
case MotionEvent.ACTION_DOWN:
if (!test.isAlive()) {
synchronized (test) {
test.start();
}
} else {
synchronized (test) {
test.notify();
}
}
break;
case MotionEvent.ACTION_UP:
// accepts the action
synchronized (test) {
try {
// doesn't goes here
test.wait(); // doesn't execute
} catch (InterruptedException e) {
e.printStackTrace();
}
}
break;
default:
break;
Probably you use too low level API for your needs. Just look at http://developer.android.com/reference/java/util/concurrent/ScheduledExecutorService.html
One thing I see is potential dangerous is that in your separate thread, you are waiting inside a synchronized statement. So when that guy is sleeping, it takes the lock with him, and therefore in your onTouchListener, none could grabbed the lock but to wait. And because the onTouchListener is controlled in the framework, it may stop running if it waits too long. I did a simple test here to prove it.
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
final Object globalLock = new Object();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (globalLock) {
System.out.println("thread1 grabbed the lock.");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1 returned the lock.");
}
}
});
t1.start();
Thread.sleep(200);
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("thread2 is waiting for the lock...");
synchronized (globalLock) {
System.out.println("thread2 got the lock");
}
}
});
t2.start();
t1.join();
t2.join();
}
}

I can't finish thread (runnable), how it is?

Thread thread;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_yippi);
final Handler hn=new Handler();
final TextView text=(TextView)findViewById(R.id.TextView01);
final Runnable r = new Runnable()
{
public void run()
{
text.settext("hi");
}
};
thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1750);
hn.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
thread.stop();}
The code here. I can not stop the runnable thread. Also, thread.stop() and thread.destroy() are deprecated. Can somebody help me? And also I don't understand how to stop the thread with the thread.interrupt() method. What's wrong?
The JavaDoc for Thread.stop() lists the following article as explanation for why stop() is deprecated: http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Most uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized).
interrupt() is more suitable to stop some Thread from waiting for something, that is probably not coming anymore. If you want to end the thread, it's best to let its run() method return.
Create a boolean variable to stop the thread and use it in while(boolean) instead of while(true).
You can use Thread.interrupt() to trigger the InterruptedException within your thread. I've added code below that demonstrates the behavior. The mainThread is where your code would be and the timer Thread is just used to demonstrate delayed triggering of the interrupt.
public class Test {
public static void main(String[] args) {
final Thread mainThread = new Thread() {
#Override
public void run() {
boolean continueExecution = true;
while (continueExecution) {
try {
sleep(100);
System.out.println("Executing");
} catch (InterruptedException e) {
continueExecution = false;
}
}
}
};
mainThread.start();
Thread timer = new Thread() {
#Override
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stopping recurring execution");
mainThread.interrupt();
}
};
timer.start();
}
}
You can use interrupt method of Thread to try stop a thread, like below code.
May be it`s useful to you.
public class InterruptThread {
public static void main(String args[]){
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
System.out.println("Thread is Runing......");
sleep(1000);
}
} catch (InterruptedException e) {
// restore interrupted status
System.out.println("Thread is interrupting");
Thread.currentThread().interrupt();
}
}
};
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Will Interrupt thread");
thread.interrupt();
}
}

calling a time consuming method from a JButtonActionPerformed

In the following lines of code when Button1 is pressed the Jframe becomes unresponsive till the execution of the encode() method is completed. But I need to update a progress bar in the Jframe displaying the progress.
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
if (flagState == 0) {
WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
} else if (flagState == 1) {
WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode());
}
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
I thought of doing this
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
if (flagState == 0) {
Thread t = new Thread(new Runnable() {
public void run() {
WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
}
};)
t.start();
} else if (flagState == 1) {
Thread t = new Thread(new Runnable() {
public void run() {
WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode());
}
};)
t.start();
}
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
and update the progress bar from the encode() method.
But I understand that it will a strong coupling between the modules and i dont want that.
I also dont think that calling a new thread every time is a good idea ( thought of ExecutorService but not sure how to use it).
What should I do to make this into a decent piece code??
Threading is definitely something you have to introduce here. Anything that takes a significant amount of time to complete should not be run in the awt event thread.
Spawning a new thread each time the button is clicked is not inherently a problem. You should consider, though, that it may be possible to spawn many threads doing the same thing before even the first completes. You could use an Executor if you want, but it probably is not necessary.
As for tracking progress, I would add another thread that periodically queries the other thread and updates the progress bar as necessary. Here's how I would structure it:
private void Button1ActionPerformed(java.awt.event.ActionEvent evt) {
disableButton1();
final Thread t;
if (flagState == 0) {
t = new Thread(new Runnable() {
public void run() {
try {
WavFile.decode(readWavFile, msg.getText(), key.getText().hashCode());
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
});
} else if (flagState == 1) {
t = new Thread(new Runnable() {
public void run() {
try {
WavFile.encode(readWavFile, msg.getText(), key.getText().hashCode());
} catch (WavFileException | IOException e) {
notes.setText(e.getMessage());
}
}
});
}
Thread monitor = new Thread(new Runnable() {
public void run() {
try {
while (notComplete(t)) {
setProgressBar(getProgress(t));
Thread.sleep(SLEEP_TIME);
}
t.join();
} finally {
enableButton1();
}
}
});
t.start();
monitor.start();
}
n the following lines of code when Button1 is pressed the Jframe becomes unresponsive till the execution of the encode() method is completed. But I need to update a progress bar in the Jframe displaying the progress.
you have issue with Concurency in Swing, you block the EDT, caused unresponsive GUI, until code ended
have look at SwingWorker for JProgressBar
use most scallable Swing Action instread of ActionListener
use implemented setEnabled() instead of if (flagState == 0) {
Multithreading is what you need, there is no other nice way i can think of don't worry about calling new threads, that's what they are there for, jvm has a thread pool ready to be used, this sort of things runs really good with threads, try it out!
Create a class that extends Runnable, implement the run method or make it call your current method, that should be enough to do this.
Also you could just make it sleep for a short time and check the status each time the sleep time goes out, if the process finished you can continue, if not, back to sleep for another short time, that way you don't have to ask that many times.
I hope it helps.

calling invokeAndWait from the EDT

I have a problem following from my previous problem. I also have the code SwingUtillities.invokeAndWait somewhere else in the code base, but when I remove this the gui does not refresh. If I dont remove it the error I get is:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread
at java.awt.EventQueue.invokeAndWait(Unknown Source)
at javax.swing.SwingUtilities.invokeAndWait(Unknown Source)
at game.player.humanplayer.model.HumanPlayer.act(HumanPlayer.java:69)
The code in HumanPlayer.act is:
public Action act(final Action[] availiableActions) {
try {
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
gui.update(availiableActions);
}
});
}
catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
return getActionPerfomed();
}
Image of threads when in debug as screen doesn't paint:
alt text http://img684.imageshack.us/img684/6669/69288941.png
Text version of stack:
ui.startup.LoginScreen at localhost:51050
-> Deamon Thread [AWT-Windows] (Running)
-> Thread [AWT-Shutdown] (Running)
-> Thread [AWT-EventQueue-0] (Running)
-> Thread [DestroyJavaVM] (Running)
The answer was instead of making the call
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
from the EDT, make it execute on a new (non EDT) thread so that later when invokeAndWait is called it functions as correctly as the thread running that command is not the EDT. The amended code is as follows:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
new GameInitializer(userName, player, Constants.BLIND_STRUCTURE_FILES.get(blindStructure), handState);
}
});
t.start();
invokeAndWait() is meant to be called from the non-GUI thread. It sends a Runnable object to the GUI thread where it will be executed.
There's no point in sending a Runnable object from the GUI-thread to itself. It has the same effect as calling run() on the Runnable object directly.
You can check before if your current calling thread is already the event dispatcher:
private void syncExec(final Runnable r) {
try {
if (EventQueue.isDispatchThread()) r.run();
else EventQueue.invokeAndWait(r);
} catch (final Exception e) {
Throws.throwRuntime(e);
}
}
Note that SwingUtilities.invokeAndWait(Runnable) simply delegates to the EventQueue.
Based on the comments, it appears you are not repainting the frame once the actions are completed. If you do not, then the screen will only be updated at what seems to be random times (when another window moves in front, perhaps).
Inside gui.update, I suggest you make the last line:
myFrame.repaint();
(more or less, depending on your circumstances).
Edit: As it turns out, the actual problem is this loop:
synchronized(performedAction){
while(!hasPerformedAction()){
try {
performedAction.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
setPerformedAction(false);
}
Since there is only one application thread (which happens to be the EDT), the result of hasPerformedAction() can never change (assuming it's a simple getter). There is no other thread to change the value. Since this infinite loop is on the EDT, the GUI can never be repainted; hence it locks up.
When using XChart java library you can show your chart on button click with this code:
JButton btn = new JButton("View chart");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
new SwingWrapper(yourChart).displayChart();
}
});
t.start();
}
});
try to execute your code from this
Executors.newSingleThreadExecutor().execute(new Runnable() {
public void run() {
}
});

Categories