GWT - Refreshing an element on the page - multithreading

Hi I play with GWT in the weekends, and I really like what i've seen
so far. I have 2 questions:
I don't really understand the execution model of my app. I think
that's because I don't know javascript. I'm assuming that there is
only one logical thread from the browser running the javascript and it
is the same thread that updates the display (disregarding asynchronous
requests). So when through js I add 50 elements to a frame, the 50
elements are displayed after all of them are added to the frame. In
other words, after the js has finished executing. Do I have it
right? Are there articles out there on this topic?
Sorry this is not a great example, but it may get my question
across. What do I do in the following situation (design):
a) update the text in a label to "starting..."
b) do a bunch of js and dom manipulation
c) update the text in the label to "finished!"
Currently, all I see is the after-effect: my dom manipulation and
"finished". The label never displays "starting..."
How can I force the label to refresh between step a & b. I've seen
some posts describing that one could use the Timer and somehow force
the element to refresh. But I can't figure out how this is achieved.
Looking forward to your suggestions. Thanks in advance.

To 1): Yes, javascript is single threaded. It is up to you to implement long running operations as non-blocking. Otherwise you're likely to run into Slow Script Warnings (see next point).
To 2): Have a look at the IncrementalCommand class (it's usage is described here). With it you can divide long running operations into chunks of smaller work and display progress updates to the user. A small example:
public class Starter implements EntryPoint {
private Label text = new Label();
private Label update = new Label();
#Override
public void onModuleLoad() {
Button btn = new Button("hit me");
btn.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
text.setText("starting...");
startIncrementalWork();
}
});
RootPanel.get().add(text);
RootPanel.get().add(update);
RootPanel.get().add(btn);
}
private void startIncrementalWork() {
IncrementalCommand cmd = new IncrementalCommand() {
private int count = 0;
#Override
public boolean execute() {
if (count >= 10000) {
text.setText("finished");
return false;
}
for (int i = 0; i < 100; i++) {
update.setText("count " + count);
count++;
}
return true;
}
};
DeferredCommand.addCommand(cmd);
}
}
Hope that helps.

Related

When a form is handled in JSF, does it all happen in one thread?

Say I have this piece of code
<p:dataTable styleClass="scheduleTable" value="#{todaySchedule.hours}" var="hour">
<p:column headerText="Hour" styleClass="hourColumn" >
#{hour.time}
</p:column>
</p:dataTable>
and in a class called todaySchedule, have a method
public List<Hour> getHours() {
final List<Hour> hours = IntStream.range(0, Hour.TIME.values().length)
.mapToObj($ -> new Hour()).collect(Collectors.toList());
for (int i = 0; i < 5; i++) {
hours.get(i).setHour(1);
}
return hours;
}
and here's the Hour class
public class Hour {
private int time;
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
}
Now, I'm not sure what JSF does behind the scenes to make this dynamic dataTable data iteration through the hours List possible, but I assume that if this is happening all in one thread, then it is okay. However, what if behind the scenes, the getHours is used in another thread that actually does the generating columns and see Hour in a bad state? This could be avoided if the getHours() method was
public List<Hour> getHours() {
final List<Hour> hours = new ArrayList<>();
for (int i = 0; i < 5; i++) {
hours.add(new Hour(i + ""));
}
return hours;
}
with the corresponding Hour class being
public class Hour {
private final int time;
public Hour(int time) {
this.time = time;
}
public int getTime() {
return time;
}
}
However, my question is that, if it wasn't changed to the latter design, can things go wrong when using basic dynamic JSF dataTable rendering due to visibility issues in Java when publishing this Hour instances?
JSF runs on top of Servlet API which serves one request in one thread, so unless you introduce more threads yourself you may expect your code to be run in a single thread.
On the other hand, you should get to know the basics of JSF life-cycle and how the bean properties are being accessed as this may cause you a lot of troubles if you don't understand it.
For example, should your Java code stay the same, adding another reference to todaySchedule.hours to your JSF would cause the getter to be called twice, thus generating the content twice. This can get really messy very quickly, so it is a good thing to do some "caching". I personally use this approach:
private List<Hour> hours = null;
private void initHours() {
this.hours = new LinkedList<>();
// Fill hours here
}
public List<Hour> getHours() {
if (this.hours == null) {
initHours();
}
return this.hours;
}
You have to be careful though at what stage of the JSF lifecycle you do this. Should you for example in a form processing method change the data affecting the list generation, the list will probably be already "cached" from the restore-view phase and the change would not be reflected when render-view phase starts. In such case you should be aware of the caching and clear the list when you need to reload it.
public void saveHours() {
// Save the data, do whatever you need to do
// This will ensure re-initializing the list on the next call
this.hours = null;
}

JavaFX: Autoscroll of TextArea with appendText but without Listeners

I've read the other articles on Stackoverflow on this topic. But none of them matches my problem exactly.
I want to log an algorithm in a TextArea. In each iteration of the algorithm the text in this TextArea should be expanded via appendText().
My first problem is: Where should I create the new Thread and how can the both threads communicate with each other (GUI and algorithm)?
In my actual design I have three important classes: The view, which holds the TextArea, the controller, which calls the algorithm and the algorithm, which takes a number of iterations and the TextArea (to call the appendText()-method on severage places in the code).
In this design the controller calls the algorithm, the algorithm iterates n times with a for-loop and after it terminates, the GUI shows the changes. But I want the GUI to show the changes simultaneously, when the algorithm calls the appendText()-method.
And my second problem is the autoscroll of the TextArea. After each appendText-call the TextArea should be scrolled completely down. But I think the solution of this problem is the same solution of my first problem.
I would be very grateful for some help.
It's pretty much impossible to answer your question completely without (a lot) more information, but the general approach I would use would be for the algorithm to have a callback to process a message, which could be invoked by each step of the algorithm. From the controller, pass an implementation of the callback which updates the text area with the message, on the FX Application Thread.
Something like:
public class Algorithm {
private Consumer<String> statusCallback ;
public Algorithm(Consumer<String> statusCallback) {
this.statusCallback = statusCallback ;
}
public Algorithm() {
// by default, callback does nothing:
this(s -> {});
}
public void performAlgorithm() {
while (! finished() ) {
doNextStep();
String statusMessage = getStatus();
statusCallback.accept(statusMessage);
}
}
}
and then
public class Controller {
private View view = ... ;
public void startAlgorithm() {
Algorithm algorithm = new Algorithm(s -> Platform.runLater(view.appendStatus(s)));
Thread t = new Thread(algorithm::performAlgorithm);
t.setDaemon(true);
t.start();
}
}
For the View you then do the following (note that you can scroll down with textArea.setScrollTop(Double.MAX_VALUE);):
public class View {
private TextArea textArea ;
public View() {
textArea = new TextArea();
// ...
}
public void appendStatus(String status) {
if (!textArea.getText().isEmpty()) {
textArea.appendText("\n");
}
textArea.appendText(status);
textArea.setScrollTop(Double.MAX_VALUE);
}
}
This should work as long as your algorithm doesn't create too many status updates too fast (so that they flood the FX Application Thread and prevent it doing its normal work).

WinForms Thread-safe Controls

I spend a lot of time working with Windows Forms controls but from a background worker thread - I suppose this is good practice really since you don't want your form to be locking up when people click buttons. To be honest, with just about everything GUI related action I normally do in a background worker thread, so the interface is nice an responsive to the user (Wish more people would do that!).
So my question is... every time I have to interact with controls I have to "Invoke" them, with something like:
if (control.InvokeRequired)
{
//
}
Standard practice right? However, this leads me to some terribly messy code, because just about every control type I have, I need a MethodInvoker delegate or something. It's adding thousands of lines of code to my protects, and its terribly time consuming.
I currently have hundreds of "property setting" methods like:
private void Safe_SetLableText(Label control, string text)
{
if (control.InvokeRequired)
{
control.Invoke((MethodInvoker)delegate
{
control.Text = text;
});
}
else
{
control.Text = text;
}
}
So, is there some other technique, or way to do this, or some way to being able to always alter a property of a control, no matter what the control is and no matter what thread im in?
something like: (pseudocode)
BackgroundWorker.RunWorkerAsync();
private void thing_to_do()
{
// We are in a background thread now
DoSomeDatabaseWorkThatTakesALongTime();
InvokeAnyControls();
// Do some stuff...
controlX.Text = "123"
controlY.Height = 300;
controlZ.text = ControlA.text;
RestoreAnyControls();
}
You could wrap your InvokeRequired code with a delegate, like so:
public static void Invoke2<TControl>(this TControl c, Action<TControl> code) where TControl : Control {
if( c.InvokeRequired ) c.Invoke( delegate() { code(c); } );
else code(c);
}
Then use it like so:
private void Safe_SetLableText(Label control, string text) {
control.Invoke2( c => c.Text = text );
}
Of course you might want better names than Invoke2, but I hope the idea sits will with you. Note that the lambda-expression syntax is a C# 3.0 feature, but the Action<T> delegate is part of .NET 2.0, so this will compile against the .NET Framework 2.0 so long as you're VS2008 or later.
I'm posting an answer to my own question because I think it will add value to the community.
1) I wanted to "simplify" my code, and one if the most important finds was that that the:
control.InvokeRequired
really isnt needed... its pretty much a given. Importantly, you CAN rely on the fact that the control will need to be invoked if you are in a background (or non-UI) thread.
2) The invocation travels "UP" the control tree, so if you have:
Form > Control > Control inside Control > etc > etc
You only need to invoke "Form" (top most), and then you can alter the properties of the child elements.
So here is my clean and simple solution to working with background workers (or non-UI threads). I have just tested this now and it works great.
public partial class Form1: Form
{
public Form1()
{
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(this.bgDoWork);
bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.bgComplete);
bgw.RunWorkerAsync();
}
private void bgComplete(object sender, EventArgs e)
{
// You are not in the UI thread now, so you can Invoke without error
this.Invoke((MethodInvoker)delegate
{
// Now you can change any property an any control within this form.
// Remember "this" refers to Form1.
this.label1.Text = "test123";
this.label2.Text = "test456";
this.label3.Text = this.label4.Text;
// You can set progress bars too, not just label text
}
}
private void bgDoWork(object sender, DoWorkEventArgs e)
{
// Do something that takes a long time
}
}
As you are already using the Background worker why don't you 'misuse' OnProgressChanged?
private void thing_to_do()
{
// We are in a background thread now
DoSomeDatabaseWorkThatTakesALongTime();
BackgroundWorker.ReportProgress(1, "state");
DoSomeMoreDatabaseWorkThatTakesALongTime();
BackgroundWorker.ReportProgress(2, YourObjectHere);
}
void OnProgressChanged(ProgressChangedEventArgs progressArgs)
{
switch(progressArgs.ProgressPercentage)
{
case 1:
// Do some stuff...
controlX.Text = "123"
controlY.Height = 300;
controlZ.text = ControlA.text;
break;
case 2:
// other stuff
YourObject obj = (YourObject) progressArgs.UserState;
// wahtever...
break;
default:
break;
}
}

Having trouble with AsyncTask using a recursive method

I've been reading about AsyncTasks and Hanlders and Loopers but I still can't figure out where I'm going wrong in my code. I'm trying to run code that will look over a Tic Tac Toe grid and determine the best move for the computer. I want this code to run in the background 'cause it can take some time and then I can update the UI level with a textbox that says something like "I'm Thinking". I've tried this a bunch of different ways, none with success.
private class PostTask extends AsyncTask<String, Integer, String> {
private Board _b;
private Welcome.Player _opp;
private int _depth;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected void SetVars(Board b, Player p, int depth){
_b = b;
_opp = p;
_depth = depth;
}
#Override
protected String doInBackground(String... params) {
Looper.prepare();
try{
_bestMove = _b.GetBestMove(_opp,_depth);
}
catch(Exception err){
_bestMove = -1;
}
return "All done";
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(_bestMove == -1){
TextView tv = (TextView) findViewById(R.id.tv_Score);
tv.setText("Had and error, couldn't make a move.");
}
FollowUpComputerMove(this);
}
The above code will work for exactly 5 moves and then it crashes. When I watch in the debugger I see new theads being created named Thread<#> AsyncTask #1. Once I get to five of those AsyncTasks it goes back to try and grab the first AsyncTask and crashes. When it crashes I'm shown the ThreadPoolExecutor.class file.
I've also read that I shouldn't be using both the AsyncTask and the Looper objects together so I've tried taking the Loooper.prepare() statement out, but then my AsyncTask fails immediately with the error message:
Can't create handler inside thread that has not called Looper.prepare() - AsyncTask inside a dialog
I've read repeatedly that you shouldn't be trying to update the UI from an AsyncTask and that often the above error is because of that, but GetBestMove isn't updating the UI thread. When I trace through to see where the error comes, it fails when calling a constructor saying it can't find the class.
Can anyone point me in the right direction? My end goal is to use one main thread and only one background thread, and just keep re-using the background thread whenever the computer needs to make a move. I know that the recursive method GetBestMove works when I run this program in a single-thread manner. But the screen freezes for too long on some moves as the method is being run. Thank you so much.
-NifflerX
Apologies for answering my own question, but the issue I was facing had nothing to do with recursion. The class I was calling was extending the class Activity, and while trying to call that from an AsyncTask the program was erroring out. When I removed the extends Activity from the class definition it started working again. Sorry for the post.
-NifflerX

Blackberry Thread Image from JSON

I am looking for a way to display images on my ListField from a background thread. First in my drawListRow i try this
path = (String) imagePaths.elementAt(index);
bit = connectServerForImage(path);
g.drawBitmap(xText, y + yText, 80, 200, bit, 0, 0);
but can't scroll smoothly throughout the list, and they say do not do networking or other blocking operations on the UI. But i also try this
private class imgConnection extends Thread
{
public imgConnection() {
super();
}
public void run() {
try {
for (int i = 0; i < imagePaths.size(); i++)
{
final int index = i;
String path = imagePaths.elementAt(index).toString();
bit = connectServerForImage(path);
image.addElement(bit);
}
}
catch (Exception e)
{
System.out.println(e.toString());
}
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_list.setSize(image.size());
subManager.add(_list);
screen.invalidate();
}
});
}
}
public void drawListRow(ListField list, Graphics g, int index, int y, int w) {
bit = (Bitmap) image.elementAt(index);
g.drawBitmap(xText, y + yText, 80, 200, bit, 0, 0);
}
but nothing happens. Any idea, comments.
You are right, i just started java development 2 weeks ago particularly BB development and i try this link. I want to add a background thread to download image after i got the path url from json return.
first thread:
_connectionthread = new Connection();
_connectionthread.start();
private class Connection extends Thread
{
public Connection()
{
super();
}
public void run() {
try {}
catch (Exception e) {}
}
}
second thread:
_imgConnectionThread = new ImgConnection();
_imgConnectionThread.start();
private class ImgConnection extends Thread
{
public ImgConnection() {
super();
}
public void run() {
try {
}
catch (Exception e)
{
}
}
}
how to update images on ListField?
Answer is based on code from - pastebin.com/90UKTHzP
Terrible code! It's really hard to read and undersand! It looks like you copy pasted several examples from different locations. Also you overriding default behavior with same behavior. Also MainScreen already has VerticalManagerField. Also you're adding list every iteration to manager which will cause IAE. And main one thread is depended on result of second one. They start at the same time, but getting json from server and it's processing could take longer time, so image thread most probably will finish his run without any result.
So main recommendation to fix it - read clean code book! Read more about java development - conventions, multithreading. Read about BB development - UI api, networking.
And finally - start only one thread to get and parse json. After you get it finished - start another thread to get images.
There some minor things that could save you more battery and processor time also - start loading images on demand - when it painted or going to be painted (user scrolls list).
By convention, Java class names start with a capital letter, so imgConnection should really be ImgConnection.
In your sample code, I don't see imgConnection being instantiated anywhere, and I don't see any call to Thread.start(), which is the way a thread i started. Without Thread.start() it is not surprising nothing is happening - the thread is never starting.

Resources