first of all I'm sorry about my English level, I'm Spanish.
I have a little problem with a progressBar in SWT application:
I have 1 Class(The application (SWT)) with all controls(progressBar, textboxes, combos, etc).
I have 1 Thread class who makes a file upload to an FTP server.
My problem is, I'm getting invalid thread access when I try to update my ProgressBar.Selection(int) from my UploadThread.
I'm trying hard to solve this problem, with Timertask(I wanna upload my progressBar every second), with events (an Event fires when UploadThread stay active) but it didn't work.
I hope you can help me with this problem.
When you use SWT, you must remember that all access to SWT objects must be performed in the SWT UI Event thread. There are a few exceptions to this, but they are typically noted in the API or rather obvious.
To make any changes to a control use the following template:
c.getDisplay().asyncExec(new Runnable() {
#Override
public void run() {
if (c.isDisposed()) return;
// ...
}
});
This will run the Runnable object in the event thread at the soonest possible time. You can even use this construct in the event thread itself, to postpone work for later - usually to get a rapid UI response.
The if (c.isDisposed()) return; construct is here to guard against the situation where the control is disposed in the time between asyncExec(...) and run() are executed.
If you need to wait for the result to be performed, use syncExec(...) instead of asyncExec(...).
How are you creating your upload thread?
If your thread implements IRunnableWithProgress and is run by a class that implements IRunnableContext, your progress bar should be able to run in a separate thread fine.
Just specify true for the fork parameter on the run method.
The run method on IRunnableWithProgress provides an IProgressMonitor for your thread to update.
Related
I'm student and I'm working on project with few of my friends. My task is to make something like class library. Classes in this library should provide API for my friend who must make GUI part of application. GUI could be made by any toolkit (Swing, JavaFX, SWT, AWT, all should work, in fact, it should work even if there is no GUI). I need to make class that waits for data to arrive from network. I don't know when data will arrive, and UI must be responsive during waiting, so I put that in different thread. Now problem is how to make GUI respond when data arrive. Well, I tought that this is asynchronous event and GUI should register event handlers, and I should call that methods when event happens. I proposed this solution:
interface DataArrivedListener{
void dataArrived(String data);
}
class Waiter{
private DataArrivedListener dal;
public void setDataArrivedListener(DataArrivedListener dal){
this.dal = dal;
}
void someMethodThatWaitsForData(){
// some code goes here
data = bufRdr.readLine();
//now goes important line:
dal.dataArrived(data);
// other code goes here
}
}
My question is:
Should I replace "important" line with something like this:
java.awt.EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or something like:
javafx.Platform.runLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or maybe I should do something completely different?
Problem is that I'm not sure which of this will work for any type of UI. If it's GUI, dataArrived() could potentialy make changes to GUI and no matter what type of GUI it is, this changes should be drawn on screen properly. I also think that it is better if I do "invoke this code later" so that my someMethodThatWaitsForData() method could trigger event and continue on with it's on work.
I appreciate your help.
Here's an Event Listener article I wrote a while back. The article explains how you write your own event listeners.
You're correct in that you want to write your own event listeners if you want your library to work with any GUI.
I'm most familiar with Swing, so yes, you'll have GUI code that looks like this:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
dal.buttonPressed(data);
}
});
If you want it to be completely agnostic to what GUI is being used the only real solution is to let the receiver handle it in dataArrived. Since every toolkit has its own implementation all you can really do to make it work with any toolkit is to disregard it. Otherwise what you will actually end up with is a list of "supported toolkits" and a case for each one.
If you just want dataArrived to be executed away from someMethodThatWaitsForData then you could make your own dispatch thread or make a new thread each time.
If you want to be truly independent of any front-end system, I would recommend creating two threads. The first is your Waiter, which will just listen for events and put them into a Queue of some sort (see the "All Known Implementing Classes" section). The second will invoke the data listener or listeners whenever the queue is not empty.
The concept of invoking a Runnable in the background is kind of deprecated since the invention of the concurrent package. The main reason that this was done in earlier days, is that the GUI code needs to be executed in a different thread, to guarantee that it stays responsive, even if the main thread is busy doing some calculations, but actual multi-threading was still in its very early days. The resulting invokeLater concept works, but comes with a strong creation overhead. This is especially annoying if you frequently have to do minor things, but each time you need to create an entire new Runnable, just to get that event into the Swing thread.
A more modern approach should use a thread-safe list, like a LinkedBlockingQueue. In this case any thread can just throw the event into the queue, and other listener/GUI-Event-handlers can take them out asynchronously, without the need of synchronization or background Runnables.
Example:
You initialize a new Button that does some heavy calculation once it is pressed.
In the GUI thread the following method is called once the button is clicked:
void onClick() {
executor.submit(this.onClickAction);
}
Where executor is an ExecutorService and the onClickAction a Runnable. As the onClickAction is a Runnable that was submitted once during Button creation, no new memory is accessed here. Let's see what this Runnable actually does:
void run() {
final MyData data = doSomeHeavyCalculation();
dispatcher.dispatch(myListeners, data);
}
The dispatcher is internally using the LinkedBlockingQueue as mentioned above (the Executor uses one internally as well btw), where myListeners is a fixed (concurrent) List of listeners and data the Object to dispatch. On the LinkedBlockingQueue several threads are waiting using the take() method. Now one is woken up as of the new event and does the following:
while (true) {
nextEvent = eventQueue.take();
for (EventTarget target : nextEvent.listeners) {
target.update(nextEvent.data);
}
}
The general idea behind all this, is that for once you utilize all cores for your code, and in addition you keep the amount of objects generated as low as possible (some more optimizations are possible, this is just demo code). Especially you do not need to instantiate new Runnables from scratch for frequent events, which comes with a certain overhead. The drawback is that the code using this kind of GUI model needs to deal with the fact that multi-threading is happening all the time. This is not difficult using the tools Java gives to you, but it is an entire different way of designing your code in the first place.
I have an user interface that is partly web based (WebView). It is connected to the Android UI through a Javascript Interface. When you tap on an element in the WebView, javascript calls up to Android and Android receives the call on the javascript/web thread. Not the UI (main) thread.
It arrives in Android in 1 or less milliseconds. No problem there. However, because I want to now change the UI, I have to switch over to the UI thread. (Android throws an exception if you modify the UI from off the main thread). I am currently using a Handler on the UI Thread and calling post().
This code (a Runnable) is then called anywhere between 120 and 300 ms later. This is a very noticeable lag for the UI to change from the user's touch.
Is there any way to get some code to run on the UI thread faster? Here is some example code:
An interface class:
public class JSInterface {
public void test() {
// Arrives here in 1ms after calling AndroidInterface.test(). Arrives n the web thread.
runOnUiThread(new Runnable() {
#Override
public void run() {
// Arrives here 100ms to 300ms after calling AndroidInterface.test(). Arrives on the main (UI) thread.
}
});
}
}
Added to a webview like this:
webview.addJavascriptInterface(new JSInterface(), "AndroidInterface");
Called in javascript like this:
AndroidInterface.test();
Thanks!
Is there any way to get some code to run on the UI thread faster?
runOnUiThread() and kin put a message on a message queue that the main application thread works off of. Much of the time, the main application thread's job is to pull a message off the queue and process it. However, the main application thread is responsible for calling most of your callbacks as well.
If you are seeing "120 and 300 ms" delays, that means one of two not-mutually-exclusive things:
The queue has quite the backlog
The main application thread is busy executing some other code
The relationship between WebView, the queue, and the main application thread is rather mysterious, compared to normal widgets, because WebView isn't a classic widget rendered in Java code. Hence, I have no idea if there is something that is occurring in your Web content that might explain this, or if this is fairly normal for WebView. You might try an experiment with simpler Web content and see whether you get similar delays, or if the delays are somehow more tied to the specific Web content that you are rendering.
Push come to shove, use Handler and postAtFrontOfQueue(). As the JavaDocs for that method note, though, this is dangerous.
After having some trouble with setting up a thread to start my MIDI sequencer I decided to simply remove it, although it would slow my UI down I would be able to use it correctly.
What I noticed however was that even when playing the Sequencer the UI was very much active, even if it was playing around 500 notes the UI worked perfectly fine.
Now I know that in C# if you are doing something intensive it is advisable to load it on a new Thread as it will free the UI. Is it the same principle in Java, it's really confused me. If so can someone explain how the UI is not being blocked?
Thanks
Edit:
The following code actually plays the Sequence
public static boolean Play() {
if(!_sequencer.isRunning()) {
try {
_sequencer.setSequence(_sequence);
_sequencer.start();
return true;
} catch (Exception e) {
Logger.Add(e.getMessage());
}
}
return false;
//Already running
}
Yes, it is the same theory. Only the Event Thread can modify the UI, and thus if you are doing anything on that thread, then you are preventing other events from working on the UI.
It may be easier to think about the Event Thread as a queue:
Show Form
Click Button
Do your work (Action)
Reset focus of Button
Update Progress Bar
Et cetera
If #3 takes long, then it may mean that your form will appear locked up. Obviously it completely depends on your definition of long. In general, it's better to work off of the Event Thread rather than on it.
It's definitely the same principal. Generally speaking you want to only do minimal work with the UI thread. If it ends up taking any significant time, it can cause the UI to be unresponsive and you can get a "Not Responding" error. You want to keep the UI thread as free as possible so it can respond to user interaction.
If your application has a graphical user interface, it's advised that you perform expensive calculations on a new Thread to keep your graphics from freezing. You can either create a SwingWorker, or use the Callable/Future idiom.
Yes, you're right. Read Threads and Swing for more info.
I am trying to implement a GUI in java but I am beginner in swing. I want to make something clear. I read that in order to keep the GUI responsive I should use the SwingWorker class to do the task in a separate thread. Ok so far.
No I have a model with around 15 methods that are remote methods. Each method returns different object type as a result than the others.
In my view the user presses a button and the appropriate method in the model is called. Without using the swingworker the GUI froze. My question is, am I supposed to create 15 subclasses of Swingworker threads and create a NEW instance of each as needed according to user's actions? Is my understanding correct? Is there a standard way for this or what I say is a correct approach?
Thanks!
Have a look at this: Simple Background Tasks.
It seems you have two concerns. Firstly, regarding the amount of code required when using SwingWorker: you do need to create a subclass of SwingWorker for each action, but that doesn't mean they need to be top-level, named classes, or in their own files. They can be anonymous classes, as shown in the article, so that the code is within your GUI's event-handling code.
Secondly, regarding instantiation of SwingWorker objects: you can't reuse a SwingWorker, but since the jobs are being executed as a result of user activity (e.g. clicking a button), you shouldn't encounter any performance problems with instantiating new objects each time.
By all means, SwingWorkers get the job done. In my experience, I haven't liked using the SwingWorkers for just one little job. I prefer to spawn off a thread, and have that thread ask the EventDispatch thread to update the GUI. Only the EventDispatch thread should update the UI, though there are a few exceptions.
I would suggest reading about threads in threads in Swing.
Though threading can get heavy, and maybe this solution would not work for you in all cases, if a seperate thread needs to spark a change in GUI, use something like,
java.awt.EventQueue.invokeLater(new Runnable()
{
public void run()
{
// this codes runs on the event dispatch thread
// update the ui here.
}
});
I'm writing an app that's basically a wrapper around a 250K JNI. The JNI (a game engine) has APIs like handle_penUp(int x, int y). Sometimes it needs to query the user from inside handle_penUp() (via callbacks into Java code), so the dialog I use to implement the query must block.
I understand that the main thread of execution can't block. So I've spawned a second thread that makes all the JNI calls that might result in callbacks that would need to block. Inside that second thread, when I need to put up a blocking dialog, I call startActivityForResult() and then acquire() on a semaphore. When onActivityResult() gets called on the main thread it calls release() on the same semaphore.
This works if my query is implemented as a new Activity, but not if I want to showDialog() within the existing Activity. Log messages tell me my thread needs a Looper. I'm adding one -- and will append info on whether it works -- but it feels as if I'm going down the wrong path here. What I need is a recipe for doing blocking dialogs (useful if only because every other platform has them and so ported code will often work that way.)
It sound very close to a problem I had with setting visible/invisible some view from the touch thread.
the problem is that you can't do some operations on the GUI form another thread (which is your case)
what you need to do is to use a Handle in your main thread
I declared it in the Activity
public static final Handler handlerVisibility = new Handler() {
public void handleMessage(Message msg) {
int visibility = msg.getData().getInt("visibility");
view.setVisibility(visibility);
}
};
I chose the option of public static so that I can access in anywhere (because I never have more that one call at a time and that I felt lazy to pass it along to the sub classes).
then what you want to do is send a message to this handler and since the Handler is in the same thread as the gui it works ^^
Message msg = MainActivity.handlerVisibility.obtainMessage();
Bundle b = new Bundle();
b.putInt("visibility", View.VISIBLE);
msg.setData(b);
MainActivity.handlerVisibility.sendMessage(msg);
That should solve your looper error and allow you to send GUI request from one thread to another
hope it helps
Jason
You definitely don't want two UI threads. There should be only one thread that communicates with the Android SDK as far as the control flow and display go (i.e. anything related to drawing, starting activities, displaying dialogs, etc).
Also, keep in mind that you don't want to actually keep your thread running - everything is based on events, so you want your code to respond to something, do something, and then exit as soon as possible.
When you say "block", what exactly do you mean? What needs to be blocked? If you simply need to stop responding to events, why not have a boolean that is set to true while the dialog is visible, and simply ignore all events while it is true?