InvokeAndBlock causing EDT violation, everytime I used after showModeless dialog - java

I am using InvokeAndBlock whenever any process based function performed. for example.
If I want to save something and it takes while to save the data then i used below code.
First show process dialog.
initProcessDialog();
progressDialog.showModeless(); // show process dialog
//Actual process
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
saveAll("SAVE_ALL",jobData);
FileUtil.removeBackupFile(jobDataDetail.getJobTemplateFileName());
progressDialog.dispose();
}
});
also added InvokeAndBlock while any action performed which is time-consuming.
backButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
initLoadingDialog();
loadingDialog.showModeless();
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
}
});
}
});
Any correction require in process ?

Since your calls to invokeAndBlock are mostly related to your own code its hard to tell what exactly you are doing.
The call to dialog.dispose() within invokeAndBlock is wrong. You need to call it after the invokeAndBlock which will work exactly the same without the EDT violation.
Codename One has one UI thread: the EDT.
invokeAndBlock opens a separate thread where you aren't allowed to access any UI related API's.

Related

How to run multiple thread properly in eclipse plugin?

My plugin checks if the user is idle for a certain amount of time. With the solution from here, I tried to work my way around. But the eclipse application becomes unresponsive until the loop ends.
Also, the message box is just a plain box with no title and buttons. Can somebody tell me what is wrong with this code?
#Override
public void earlyStartup() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
//while(true) {
for (stop=System.nanoTime()+TimeUnit.MINUTES.toNanos(1);stop>System.nanoTime();) {
Display.getDefault().addFilter(SWT.KeyUp, new Listener() {
#Override
public void handleEvent(Event event) {
stop=System.nanoTime()+TimeUnit.MINUTES.toNanos(1);
System.out.println("checkpoint 1");
}
});
}
Shell shell = new Shell(Display.getDefault());
MessageBox dialog =
new MessageBox(shell, SWT.ICON_INFORMATION | SWT.OK);
dialog.setText("Alert!");
dialog.setMessage("You have been idle for the last 3 minutes.");
shell.open();
stop=System.nanoTime()+TimeUnit.MINUTES.toNanos(1);
System.out.println("checkpoint 2");
}
});
}
Display.asyncExec does not run code in a separate thread. It runs the code in the main UI thread as soon as it is available. The UI thread will be blocked until the code ends.
Instead you can run code in a normal Java thread. But you must call asyncExec to execute any UI code you want to run from the thread.
In your actual code you should only be calling Display.addFilter once. This adds a listener which will be called every time the key up event occurs from then onwards. Since this is UI code you can't actually run this in a background thread at all.
So you can't use a loop like you have shown. You have to keep track of things in the key listener, updating each time the listener is called.

What does a Swing Call mean?

I have a project that takes time to load everything so I create a splash screen that tells the user through a progressbar how much time it will take to fully load and show the UI, but I'm facing a problem.
When I create my splash, this shows up correctly but then I create and initialize the Principal frame and everything freeze until this has fully load.
So, I try to load my Principal frame in a thread using SwingWorker (and it works) but after unknown NullPointerExceptions and reading a lot I found that this is a terrible idea because I am not creating my UI in the EDT, so here I am stuck.
I know that I must do Swing Calls in the Event Dispatch Thread (EDT) and non-swing heavy work in SwingWorkers but initialize the Swing Components of my Principal Frame are a heavy work too so, what should I do?
I have read some question here, specially this, and I think I get it but I have doubts. Taking that example:
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
new SplashScreen();
}
});
// Code to start system (nothing that touches the GUI)
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
new MainFrame();
}
});
//.. etc
And reading this site that says:
The Swing framework manages component drawing, updates, and event handlers on the EDT.
Is creating a new component a Swing Call? If it is, What should I do if new MainFrame() will take some time because the project has a lot of components to initialize?
How do I tell the Splash something like "Program loaded 50%"?
What does a Swing Call means and how can I do a correct use of invokeLater and SwingWorker? Maybe the solution is too obvious or have already an answer, but I can't see it and I apologize if this is the case.
Thanks!
You're on a right track. But don't use invokeAndWait (if you have to only) - use invokeLater:
invokeAndWait
Causes doRun.run() to be executed synchronously on the AWT event dispatching thread.
invokeLater
Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread.
Consider that block wrapped doLater is run on EDT thread and code wrapped in doOutside is invoked in another thread (and that's why you don't block the UI):
EDIT:
As pointed out in the comments I add the explanations for the concepts I'll use.
doLater {
// here goes the code
}
is a concept for:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// here goes the code
}
});
And
doOutside {
// here goes the code
}
is a concept for:
new Thread(new Runnable() {
#Override
public void run() {
// here goes the code
}
}).start();
doLater {
final MainFrame m = new MainFrame();
doOutside {
// handle heavy operation
final int result = 1;
doLater {
m.setResult(result);
}
}
}
Conclusion: everything that touches Swing in some way must be run on EDT.
If you want to update percentages:
doLater {
final MainFrame m = new MainFrame();
doOutside {
// handle progress
for(int i = 0; i < someSize; ++i) {
final int progress = i;
doLater {
m.getProgressBar().setProgress(progress);
}
}
}
}
I hope you understand the concept now. The SwingWorker just do exectly something as doOutside === doInBackground & doLater === done/progress
Btw. The code above is a real code: lookup Griffon framework in Groovy.

Applets - init(), EDT and threads

Java is not my mother tongue and I've been fighting with this problem for a little while.
Basically, I am finding a behavioural difference between calling method switchApplets() directly from init(), and calling it from within a new thread spawned by init().
The consequence of calling it from inside the new thread is that the new applet whitescreens -- until/unless the user resizes or minimizes their browser. If called at the end of init(), the new UI renders immediately without any input from the user. But that's not an option because it doesn't wait for the thread to finish its prep work.
Trimmed-down code:
public class PreLoader extends Applet implements AppletStub {
static JProgressBar pBar = null;
static JLabel message;
public void switchApplets() {
try {
Class main_class = Class.forName("MainClass");
Applet main_applet = (Applet)main_class.newInstance();
removeAll();
setSize(0,0);
setLayout(new GridLayout(1,0));
add(main_applet);
main_applet.init();
main_applet.start();
main_applet.setStub(this);
}
catch (Exception e) {
}
}
public void init() {
pBar = new JProgressBar(0, 100);
pBar.setValue(0);
pBar.setStringPainted(true);
message = new JLabel("Beginning work!");
add(message);
add(pBar);
FlowLayout flow = new FlowLayout();
setLayout(flow);
Thread t = new Thread ( new Runnable () {
public void run ()
{
longRunningFunction1();
longRunningFunction2();
message.setText("Work complete! Stand by..");
switchApplets(); //does NOT work as intended from here
return;
}
} );
t.start();
//switchApplets(); //works as intended if called HERE
}
public void longRunningFunction1() {
//perform some tasks, advance progress bar
}
public void longRunningFunction2() {
//perform some tasks, advance progress bar
}
public void start() {
return;
}
public void appletResize(int width, int height) {
return;
}
}
I tried making init() wait for the thread to finish so that I could call switchApplets() from there, but that only blocked the EDT and prevented the UI from updating. Also tried playing with SwingUtilities' invokeLater/invokeAndWait, but even though switchApplets() gets run on the EDT, it seems that it MUST be called directly from init() (or at least the thread init is running on) to have the desired effect.
Why does calling switchApplets() from within a new thread result in a slightly different (and unwanted) UI behaviour?
The consequence of calling it from inside the new thread is that the new applet whitescreens -- until/unless the user resizes or minimizes their browser.
It's likely a deadlock caused by trying to do UI code on the wrong thread.
I tried making init() wait for the thread to finish so that I could call switchApplets() from there, but that only blocked the EDT and prevented the UI from updating.
You're on the right track. You need to call switchApplets() only from the EDT, and only after the work is done on the other thread.
Are you sure you tried using invokeLater() or invokeAndWait() from within the spawned thread after the long running functions were done? It's been a long while since I did applets but I'm not aware of any applet-specific reason why it wouldn't work, and it would work in any other case. I.e.,
public void run()
{
longRunningFunction1();
longRunningFunction2();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
message.setText("Work complete! Stand by..");
switchApplets();
}
});
}
However, the most proper way to do this is with a SwingWorker rather than a manually created thread. SwingWorker (which is not nearly as well-known as it should be) is designed exactly for the goal of performing background tasks on a separate thread while still being able to update the GUI with progress updates and the results. E.g.,
new SwingWorker<Void,Void>() {
#Override
protected Void doInBackground() { // is called on a background thread
longRunningFunction1();
longRunningFunction2();
return null;
}
#Override
protected void done() { // is called on the Swing thread
message.setText("Work complete! Stand by..");
switchApplets();
}
}.execute();
The Void stuff is because SwingWorker is also capable of returning results and sending intermediate progress updates, but this example doesn't use those features.
You indicated that your long running functions are also updating a progress bar. That's another thing that should happen only on the Swing thread. In practice you can often get away without it, but it's dodgy. Your progress updates can use one of the SwingUtilities.invoke methods, or the mechanisms of SwingWorker; either should work. (SwingWorker itself provides two different ways to do it: Call addPropertyChangeListener (Swing thread) and setProgress (background thread), or call publish (background thread) and override process (Swing thread).)
Also, a small suggestion: if it's inconvenient to deal with a checked exception (or impossible to usefully do so), rather than catching and ignoring it, you should at least catch & rethrow it as an unchecked exception:
catch (Exception e) {
throw new RuntimeException(e);
}
That way, the stacktrace and error message of any exception will not be lost.

Java: Let other threads know if GUI is ready to use

I'm writing an application which parses XML files (continuously) and show the data in a GUI (Swing). The ParseThread is in the CoreProject, and the GUI is in the GUIProject.
The start of the ParseThread is connected to a JCheckBoxMenuItem with an ItemListener. The value of setSelected() is set directly after adding to the Menu. At this time the GUI does not contain the Component which the ParseThread needs to show the parsed Data.
My Solution is, that the ParseThread should wait until the GUI is build completely.
I thought of something like an EventQueue but I have no Idea how to code one.
My Solution is, that the ParseThread should wait until the GUI is build completely. I thought of something like an EventQueue but I have no Idea how to code one.
you have got issue with Concurency in Swing, your hard and long running task should be moved to the Background task, for Swing there are two possibilities
(easy & simple) use Runnable#Thread, output to Swing GUI must be wrapped into invokeLater(), including thread safe methods as are setText, append e.i.
use SwingWorker
EDIT
please to check my visulaizations for Runnable#Thread this is the same thing as you connect server, parse long file e.i.,
with invokeLater() I cannot be sure that the component exists until the call
create GUI,
show GUI,
some (Swing / Util) Timer or user action to invoke code that is/are redirected out of Swing EventDispatchThread, for this reason there are Runnable#Thread or SwingWorker
I'm suggest two easiest of possible ways
Ok, I got my problem...
The GUI is created like this:
EventQueue.invokeAndWait(new Runnable() {
#Override
public void run() {
try {
Mainframe frame = new Mainframe();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
And at construction of the Object Mainframe this code will be executed:
final JCheckBoxMenuItem chckbxmntmParsing = new JCheckBoxMenuItem("Parsing");
chckbxmntmParsing.setName("mainframe.menu.data.parsing");
localeChangedListener.add(chckbxmntmParsing);
chckbxmntmParsing.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (chckbxmntmParsing.isSelected()) {
parseManager.startParsing();
} else {
parseManager.stopParsing();
}
}
});
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
boolean enabled = false;
String prop = PropertyManager.get().getProperty("parser.continuousparsing.enabled");
if (prop != null) {
if (prop.trim().equals("true") || prop.trim().equals("1")) {
enabled = true;
}
}
chckbxmntmParsing.setSelected(enabled);
}
});
So the ParseThread will start after GUI is build.
Sorry for stealing your time

Get error exception when using the sleep function

I want to delay my application for a while while a melody is playing, and when it's finished change the image on an imageview.
public void addListenerOnButtons() {
harmonicaTecknad= (ImageView)this.findViewById(R.id.harmonicatecknadspelautblas);
harmonicaTecknad.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
harmonicaTecknad.setImageResource(R.drawable.harmonicatecknadtryckrood);
RunAnimations();
utblas=MediaPlayer.create(SpelaTonerActivity.this, R.raw.utblas4);
utblas.start();
Thread timer = new Thread(){
public void run() {
try { // The delay should occur here
sleep(utblas.getDuration());
} catch(InterruptedException e) {
e.printStackTrace();
} finally {
harmonicaTecknad.setImageResource(R.drawable.harmonicatecknad1);
}
}
};
timer.start();
}
}
I get an exception error, obviously I cannot set the image inside the thread, so where should I set it?
This is all explained in details, with examples, in the android documentation:
Android offers several ways to access the UI thread from other
threads. You may already be familiar with some of them but here is a
comprehensive list:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Handler
[...]
Unfortunately, these classes and methods could also tend to make your
code more complicated and more difficult to read. It becomes even
worse when your implement complex operations that require frequent UI
updates.
To remedy this problem, Android 1.5 and later platforms offer a
utility class called AsyncTask, that simplifies the creation of
long-running tasks that need to communicate with the user interface.
Write harmonicaTecknad.setImageResource(R.drawable.harmonicatecknad1); code on UI thread because you can not write UI code to non UI thread.
So simply replace above line of code with
runOnUiThread(new Runnable()
{
#Override
public void run()
{
harmonicaTecknad.setImageResource(R.drawable.harmonicatecknad1);
}
});
If you are still getting error then for testing purpose just change sleep(utblas.getDuration()); with sleep(1000);
As the other answers say, you need to set the image from the UI thread. However, while you can use Thread.sleep(), you should in general avoid using sleeps for logic. Most classes have some way to get callbacks when things happen - for example in your case you can use MediaPlayer.OnCompletionListener. You register for a callback from the media player, and that callback will always be on the UI thread. This is what it looks like:
public void addListenerOnButtons() {
harmonicaTecknad= (ImageView)this.findViewById(R.id.harmonicatecknadspelautblas);
harmonicaTecknad.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
harmonicaTecknad.setImageResource(R.drawable.harmonicatecknadtryckrood);
RunAnimations();
utblas=MediaPlayer.create(SpelaTonerActivity.this, R.raw.utblas4);
utblas.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
harmonicaTecknad.setImageResource(R.drawable.harmonicatecknad1);
}
};
utblas.start();
}
}

Categories

Resources