Skip to main content

(Important!) Dialog text messed up when shown from inside a thread

24 replies [Last post]
ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

Hello,

I've raised the issue before but till now the problem is not solved.
When showing a Dialog with a long text, the text gets disordered and some of it repeated.
This scenario happens when i show a Dialog from inside a Thread which had done some HTTP operation and displays the result in a Dialog.

Anybody experiencing similar behavior?

---- code ---
new Thread(new Runnable() {
public void run() {
try {
//http operation
Dialog.show("title",responseText, "ok", null);
// ......
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
myinstinct
Offline
Joined: 2008-10-24
Points: 0

wow, I just experienced the same problem.

I'm not calling this from another thread at all.

The dialog looks fine in the Sprint WTK, but on the actual device I am seeing a dropped word (see note below), a dialog body that is almost twice as long as it should be with an extra copy of the last 2 paragraphs.

[code]
Dialog.show("Permission Check", "This app has been previously installed.\n\nInstalling now, will invalidate the previous installation.\n\nContact xxxxx @ xxxxxxxx-xxxxxxxx.com with any questions.\n\n\n\nOK to install now?", "OK", "CANCEL");
[/code]

On the device, the word "installation" is dropped (after the word previous) - actually it's not dropped, it appears on a new line after the last paragraph "OK to install now?"

and the 2 last paragraphs "Contact xxxxx @ xxxxxxxx-xxxxxxxx.com with any questions." and "OK to install now?" show up again after the word "installation"

myinstinct
Offline
Joined: 2008-10-24
Points: 0

ok, I partially solved this - at least the error related to the displaced word.

We had a problem with TextArea a while back that resembled this problem.

For me, it was a matter of the font specified for the DialogBody in your resource file - I had one specified for "Unselected" style but not for "Selected" style.

That fix alone has not solved the issue with the last 2 paragraphs being duplicated - still working on that.

----------------------------------
Message was edited by: myinstinct

Adding link to previous TextArea message thread here

http://forums.java.net/jive/thread.jspa?messageID=387209&#387209

myinstinct
Offline
Joined: 2008-10-24
Points: 0

ok, it turns out that all my problems (at least with the Dialog) were/are related to Styles.

I went back into the LWUIT Designer and made sure that each style component set for the "Selected" style was also set for the "Unselected" style.

Oddly enough - there were only two differences

1) a DialogBody.transparency = 0 on the Selected tab that was missing from the Unselected tab

2) a DialogBody.padding on the Unselected tab that was not on the Selected tab.

I can't imagine the transparency being the issue - most likely the padding. After changing those, my Dialog on the device no longer duplicates anything and appears the same as it does in the WTK.

FWIW, my DialogBody padding is the same as my TextArea.padding - I have not tested if there is a relationship there though.

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

I didn't set any property for the DialogBody in my theme, and i was still having this problem.

For the time being only callSerially solved my problem :S

myinstinct
Offline
Joined: 2008-10-24
Points: 0

I understand - I was just passing it on in case someone else encounters similar issues.

The two things that are odd: 1) the WTK emulator worked fine, the problem was only on the device; and 2) the only changes I made to correct it were in the .RES file

vprise
Offline
Joined: 2003-11-07
Points: 0

I explained it several times including a rather detailed explanation.
The issue isn't in dialog its in TextArea (the content of the dialog body is really a text area), when a text area is accessed by multiple threads its line breaking logic suffers from a race condition hence causing "issues". Using call serially solves these issues by eliminating said race condition.

This is not a trivial fix without a performance penalty, since text area is one of the most performance sensitive areas in LWUIT we won't do this.

pksm
Offline
Joined: 2010-01-14
Points: 0

OK. Now I am thoroughly confused.

Acc. to the documentation:
invokeAndBlock(java.lang.Runnable r)
Invokes runnable and blocks the current thread, if the current thread is the edt it will still be blocked however a separate thread would be launched to perform the duties of the EDT while it is blocked.

callSerially(java.lang.Runnable r)
Causes the runnable to be invoked on the event dispatch thread.

Since I am using invokeAndBlock to run my runnable, doesn't that mean that it is running on the EDT itself? In such a case, I think the mentioned race condition should not be happening.
Or, is it that even when running a Runnable with invokeAndBlock, I need to have calls to callSerially() for any Dialogs?

Please throw some light on this.

Thanks,
Preet

Mixa

I can't understand this - the purpose of Display.callSerially() is
exactly opposite - it is intended to not block EDT - you perform long
activities in separate thread then 'pass results' to EDT via
callSerially()

Your case is not quite clear for me, but I feel you're doing something
wrong there...

Mike

On Mon, Apr 12, 2010 at 1:40 PM, wrote:
> lemonpassion, Mixa
> thank you for your replies.
> Mixa i can't use the Display.callSerially() cause there are other operations waiting for the feedback of the Dialog and can't let the EDT hang until all the operations are done.
>
> Lemonpassion: So you create a Container (as body) and add the TextArea and then u add the container (body) in the function: Display.show(String title, Component body, Command[] cmds)?
>
> thanx again.
> [Message sent by forum member 'ghady_rayess']
>
> http://forums.java.net/jive/thread.jspa?messageID=396442
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
For additional commands, e-mail: users-help@lwuit.dev.java.net

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

Hello Mixa,

My concern for using Display.callSerially is that i'm waiting for the response of the Dialog.show, and accordingly i'm doing some other operations. As far as i know, it is recommended to keep all the operations inside the Dislay.callSerially as short as possible which is not my case :S. Although now i think i'll be using callSerially since nothing else is working.
Lemonpassion: putting the TextArea in a container and calling the Dialog.show.. did not work for me.
Regrads,

myinstinct
Offline
Joined: 2008-10-24
Points: 0

I think this construct is upside down - you need to guarantee that the HTTP is completed before trying to display responseText

do the HTTP access in a thread using invokeAndBlock(), then when it is completed, display the LWUIT dialog

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

Hello Myinstinct

this is what i'm doing, i'm waiting for the http request to finish, then displaying the text in a Dialog. However, i have to wait for the response of the Dialog (since it's an ok/cancel Dialog) then i do some more operations and finally show a new form.

So my question: is it okay to put so many operations inside the callSerially method.

My Second question: Why do we have to put Dialog.show in a callSerially method while it's okay to call directly form.show, although Dialog actually extends the class Form!
-----------------------------------------------------------------

the code will look like this.

new Thread(new Runnable() {
public void run() {
try {
//http operation

Display.getInstance().callSerially(new Runnable() {
public void run() {
[b] if(Dialog.show(title, body, ok, cancel)){ [/b]
/// some operations
// form.show();
}else{
/// some operations
// form.show();
}
}
});

// ......
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();

myinstinct
Offline
Joined: 2008-10-24
Points: 0

I don't understand why you want to do all that in a separate thread.

I would (and do) only put the HTTP part in the thread - i don't know if this is the best way, but it has worked for me over the past 18 months.

In this example the contactServer() method represents the code it takes to do the actual HTTP access.

something like

[code]
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
returnText = contactServer(url);
}
});
if(Dialog.show(title, returnText, ok, cancel)){
/// some operations
// form.show();
}else{
/// some operations
// form.show();
[/code]

if your "///some operations" comment represents more HTTP activity, then that should also be called from a diff thread.

at least that is how I would do it.

RE: your 2nd question - Any luck you've had calling Form.show() from another thread is just that - pure luck, it will eventually bite you - I did the same thing at first and it worked most of the time, but not all the time.

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

myinstinct: thanx for the valuable feedback.

fair enough, we can put the http thread in the invokeAndBlock method to keep the code clean.

However, in most cases, the whole code-section is executed from a menu action or a button click which in turn spans a new Thread (actionPerformed). So the Dialog.show should again be placed in a callSerially method do avoid the bad rendering of the text. so should i place the whole remaining code in a callSerially method like this?
------------------------------
Display.getInstance().callSerially(new Runnable() {
public void run() {
if(Dialog.show(title, body, ok, cancel)){
/// some operations
// form.show();
}else{
/// some operations
// form.show();
}
}
});
----------------------------------

And for the second question: Almost, if not all the Form.show (except the first form) are called from within a thread :S, so should i place them in callSerially as well?

myinstinct
Offline
Joined: 2008-10-24
Points: 0

no, I wouldn't and don't do the remaining code in a callSerially.

and no, to form.show() from actionPerformed in a callSerially() as well

don't overthink this - I did for months until I got my head around it

I treat the actionPerformed method as part of LWUIT and don't worry about the fact that it may technically be another thread - I think the key is that it's a LWUIT created thread and LWUIT knows how to deal with that.

I could be totally wrong - but it works for me.

vprise
Offline
Joined: 2003-11-07
Points: 0

True.
Just so we are clear:
LWUIT always uses the EDT for all its callbacks (if not its a bug with possible minor exception for the HTML component but that's a documented special case).

So actionPerformed, paint*() etc. will always be on the EDT.

None LWUIT callback (e.g. MIDP API's such as startApp() etc.) will NEVER occur on the EDT and that is also guaranteed.

pksm
Offline
Joined: 2010-01-14
Points: 0

Hi,
Even I am facing the same issue when I call the static show method of Dialog from a new Thread. Sometimes the text becomes all messed up, same string is printed twice.

@vprise
What do you suggest as the final solution for this issue/problem?

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

i think myinstinct gave the best solution for this.

call the http thread in the invokeAndBlock method.

then call the Dialog.show (which should be in the LWUIT (EDT) thread).

If for some reason u had to call the Dialog.show inside a separate thread then i guess you have to use it inside the Display.callSerially method.

pksm
Offline
Joined: 2010-01-14
Points: 0

Still the same issue.
I have a Runnable that does some task and asks the user a question (Dialog) and then continues the processing.
I am running it using invokeAndBlock()
However, this Dialog text issue is still there although the frequency has decreased.
What to do now?

Thanks,
Preet

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

can u post a sample code

lemonpassion
Offline
Joined: 2008-09-23
Points: 0

We've experienced this. What I did was to use the show() function that uses a Component (Container using a BoxLayout with just a TextArea) instead of the String for the body.

Hope this helps.

Mixa

I would say that it is an EDT issue - try to move show() call to EDT
thread using something Display.callSerially() or invokeAndBlock()

Mike

On Mon, Apr 12, 2010 at 7:08 AM, wrote:
> We've experienced this. What I did was to use the show() function that uses a Component (Container using a BoxLayout with just a TextArea) instead of the String for the body.
>
> Hope this helps.
> [Message sent by forum member 'lemonpassion']
>
> http://forums.java.net/jive/thread.jspa?messageID=396410
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
> For additional commands, e-mail: users-help@lwuit.dev.java.net
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@lwuit.dev.java.net
For additional commands, e-mail: users-help@lwuit.dev.java.net

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

lemonpassion, Mixa
thank you for your replies.
Mixa i can't use the Display.callSerially() cause there are other operations waiting for the feedback of the Dialog and can't let the EDT hang until all the operations are done.

Lemonpassion: So you create a Container (as body) and add the TextArea and then u add the container (body) in the function: Display.show(String title, Component body, Command[] cmds)?

thanx again.

lemonpassion
Offline
Joined: 2008-09-23
Points: 0

Yup. :)

ghady_rayess
Offline
Joined: 2009-01-09
Points: 0

interesting.. will give it a try!